module m_read_OSISAF_data

contains

  ! Reads OSISAF ice drift data
  ! 2012-11-13: Geir Arne Waagbø (met.no)
  subroutine read_OSISAF_data(driftfile, gr, data, numdata, var, offset)
    use nfw_mod
    use mod_measurement
    use mod_grid
    implicit none

    character(*), intent(in) :: driftfile
    integer, intent(in) :: numdata
    type(measurement), dimension(numdata),intent(inout) :: data
    type(grid), intent(in) :: gr
    real, intent(in) :: var
    character(len=1), intent(in) :: offset

    integer :: dimids(2)
    integer , dimension(2) :: dimsizes

    integer :: lon_id, lat_id, dx_id, dy_id, qflag_id
    real, dimension(:,:), allocatable :: drlon, drlat, drdX, drdY
    integer, dimension(:,:), allocatable :: qflag

    integer :: ncid
    real, dimension(1) :: fillval

    integer :: i,j,k,icomp
    integer :: drnx, drny
    logical :: valid

    ! Get dimensions of drift file
    call nfw_open(driftfile, nf_nowrite, ncid)
    call nfw_inq_varid(driftfile, ncid, 'dX', dx_id)
    call nfw_inq_vardimid(driftfile, ncid, dx_id, dimids)
    do i = 1, 2
       call nfw_inq_dimlen(driftfile, ncid, dimids(i), dimsizes(i))
    end do
    drnx=dimsizes(1)
    drny=dimsizes(2)

    if (gr % reg) then
       print *,'NB: OSISAF data should be specified as irregular !'
       print *,'    Currently it is set as regular..'
       print *,'(read_OSISAF_data)'
       call exit(1) 
    end if

    ! Which should match numdata dimension 
    ! NB !!! Mult by 2 for two vector components
    if (2*drnx*drny /= numdata .or. 2*drnx*drny /= gr%nx) then
       print *,'Different dimensions - data file and specified'
       print *,'dimsizes(1)=',drnx
       print *,'dimsizes(2)=',drny
       print *,'nx         =',gr%nx
       print *,'(read_OSISAF_data)'
       call exit(1) 
    end if

    ! Read data from drift file
    allocate(drlon(drnx,drny))
    allocate(drlat(drnx,drny))
    allocate(drdX(drnx,drny))
    allocate(drdY(drnx,drny))
    allocate(qflag(drnx,drny))

    call nfw_inq_varid(driftfile, ncid, 'lon', lon_id)
    call nfw_get_var_double(driftfile, ncid, lon_id, drlon)
    call nfw_inq_varid(driftfile, ncid, 'lat', lat_id)
    call nfw_get_var_double(driftfile, ncid, lat_id, drlat)
    call nfw_inq_varid(driftfile, ncid, 'dX', dx_id)
    call nfw_get_var_double(driftfile, ncid, dx_id, drdX)

    ! Change dY_v1p4 to dY from version 1.4 of OSISAF product file
    call nfw_inq_varid(driftfile, ncid, 'dY_v1p4', dy_id)
    call nfw_get_var_double(driftfile, ncid, dy_id, drdY)

    call nfw_get_att_double(driftfile, ncid, dx_id, '_FillValue', fillval)

    where (abs(drdX - fillval(1)) < 1e-4 * fillval(1))
       drdX = gr % undef
    end where

    call nfw_get_att_double(driftfile, ncid, dy_id, '_FillValue', fillval)

    where (abs(drdY - fillval(1)) < 1e-4 * fillval(1))
       drdY = gr % undef
    end where

    ! Change status_flag_v1p4 to status_flag from version 1.4 of OSISAF product file
    call nfw_inq_varid(driftfile, ncid, 'status_flag_v1p4', qflag_id)
    call nfw_get_var_int(driftfile, ncid, qflag_id, qflag)

    call nfw_close(driftfile, ncid)

    k = 0
    do icomp = 1, 2
       do j = 1, drny
          do i = 1, drnx
             k = k + 1

             valid = qflag(i,j) == 30 ! Only use observations with quality_flag==30
             if (icomp==1) then
                data(k)%id = 'DX'//offset
                data(k)%d = drdX(i,j)
                valid = valid .and.  abs((drdX(i,j)-gr%undef) / gr%undef) > 1e-4
             else
                data(k)%id = 'DY'//offset
                data(k)%d = drdY(i,j)
                valid =  valid .and. abs((drdY(i,j)-gr%undef) / gr%undef) > 1e-4
             end if

             if (.not. valid .or. mod(i,2)==0 .or. mod(j,2)==0) then
                ! Skip invalid observations, or observations on grid points with
                ! even i- or j-indices (to avoid over assimilation)
                data(k)%d = gr%undef
             end if

             data(k)%ipiv = i  ! Not really used for ice drift
             data(k)%jpiv = j  ! Not really used for ice drift
             data(k)%i_orig_grid = i ! Used for ice drift
             data(k)%j_orig_grid = j ! Used for ice drift
             data(k)%lat=drlat(i,j)
             data(k)%lon=ang180(drlon(i,j))
             ! Each vector represents the average drift of a 120kmx120km area of sea ice
             ! The a1 value should be in meters, although other values are in km
             data(k)%a1 = 1.4*60000 ! 1.4 represents square root of 2
             data(k)%ns = 1
             data(k)%var = var ! fom idrft.hdr specification
             data(k)%depth = 0.0
             data(k)%status = valid
          enddo
       enddo
    enddo
    print *, 'Number of data read:', k, gridpoints(gr)

  end subroutine

end module


