module amip_forcing_mod

    use config_mod
    use NetCDF

    implicit none

    private

    public setup_amip_forcing
    public finalize_amip_forcing
    public update_sst_and_sic

    real(kind=8),pointer     :: AMIP_sst(:,:)
    real(kind=8),pointer     :: AMIP_sic(:,:)

    ! consider precision of the netcdf files
    real(kind=8) :: sst(GridNX,GridNY)
    real(kind=8) :: sic(GridNX,GridNY)
    real(kind=8),allocatable :: time(:)

    integer      :: year
    real(kind=8) :: ndays,deltaT,maxTime

    integer      :: ncidSST,varidSST,ncidSIC,varidSIC

contains

    subroutine setup_amip_forcing(yy,mm,dd,dtime)

        use CPLNG

        integer, intent(in) :: yy,mm,dd,dtime

        AMIP_sst  => CPLNG_FLD(CPLNG_IDX('AMIP_sst'))%D
        AMIP_sic  => CPLNG_FLD(CPLNG_IDX('AMIP_sic'))%D

        year=yy
        deltaT=dtime/86400.

        maxTime=-9999.
        ncidSST=-9999
        ncidSIC=ncidSST

        call days_since_refdate(yy,mm,dd,ndays)

    end subroutine setup_amip_forcing


    subroutine finalize_amip_forcing

        call close_file
        call flush(LOGLUN)
        close(LOGLUN)

    end subroutine finalize_amip_forcing


    subroutine update_sst_and_sic(lfixyr)

       logical, intent(in) :: lfixyr
       integer :: i

       ! open next file if leg extends across New Year
       do while ( ndays > maxTime )
           call close_file
           call open_file
           maxTime=maxval(time)
       enddo

       ! find date in time axis
       do i=1,size(time)
           if (time(i-1)<=ndays .and. time(i)>ndays) exit
       enddo
       if (LDebug) write(LOGLUN,*) '...time(i-1),ndays,time(i)',time(i-1),ndays,time(i)
       call read_file(i)

       AMIP_sst=sst
       AMIP_sic=sic

       ndays=ndays+deltaT

    end subroutine update_sst_and_sic


    subroutine days_since_refdate(yy,mm,dd,nd)

        integer, intent(in)       :: yy,mm,dd
        real(kind=8), intent(out) :: nd
        integer                   :: dpm(12)
        logical                   :: leapyear

        leapyear=(mod(yy,4)==0 .and. (mod(yy,100)/=0 .or. mod(yy,400)==0))

        ! sets correct number of days for Jan 1 of year yy
        ! refdate is Jan 1, 1850 (in AMIP forcing dataset for PRIMAVERA)
        nd=(yy-1850)*365+int((yy-1848)/4)-int((yy-1800)/100)+int((yy-1600)/400)

        if (leapyear) nd=nd-1

        dpm=(/31,28,31,30,31,30,31,31,30,31,30,31/)
        if (leapyear) dpm(2)=29

        if (mm>1) then
           nd=nd+sum(dpm(1:(mm-1)))+dd-1
        else
           nd=nd+dd-1
        endif

    end subroutine days_since_refdate


    subroutine open_file

        character (len=200) :: fname
        integer :: dimTime, lenTime, varTime

        ! open files and assign varIDs
        write(fname,'(A,A,I4,A)') trim(AmipFileRoot),'_sst_',year,'.nc'
        write(LOGLUN,*) 'AMIP: open SST file ',trim(fname)
        call nf90_chkerr(nf90_open(trim(fname),NF90_NOWRITE,ncidSST))
        call nf90_chkerr(nf90_inq_varid(ncidSST,'sst',varidSST))

        write(fname,'(A,A,I4,A)') trim(AmipFileRoot),'_sic_',year,'.nc'
        write(LOGLUN,*) 'AMIP: open SIC file ',trim(fname)
        call nf90_chkerr(nf90_open(trim(fname),NF90_NOWRITE,ncidSIC))
        call nf90_chkerr(nf90_inq_varid(ncidSIC,'sic',varidSIC))

        ! load time (assume SST and SIC files share the same time axis)
        call nf90_chkerr(nf90_inq_dimid(ncidSST,'time',dimTime))
        call nf90_chkerr(nf90_inquire_dimension(ncidSST,dimTime,len=lenTime))

        if (allocated(time)) deallocate(time)
        allocate(time(0:lenTime))

        if (LDebug) write(LOGLUN,*) 'Number of timesteps in SST file: ',lenTime

        call nf90_chkerr(nf90_inq_varid(ncidSST,'time',varTime))
        call nf90_chkerr(nf90_get_var(ncidSST,varTime,time(1:lenTime)))

        ! add an artifical time step
        time(0)=2.*time(1)-time(2)

    end subroutine open_file


    subroutine close_file

        ! don't try closing files at first pass

        if ( ncidSST > 0 ) then
            write(LOGLUN,*) 'AMIP: close SST file '
            call nf90_chkerr(nf90_close(ncidSST))

            write(LOGLUN,*) 'AMIP: close SIC file '
            call nf90_chkerr(nf90_close(ncidSIC))

            year=year+1
        endif

    end subroutine close_file


    subroutine read_file(tstep)

        integer,intent(in) :: tstep

        if (LDebug) write(LOGLUN,*) '...read timestep ',tstep

        ! read SST
        call nf90_chkerr(nf90_get_var(ncidSST,varidSST,sst, &
        &                start=(/1,1,tstep/),count=(/GridNX,GridNY,1/)))

        ! read SIC
        call nf90_chkerr(nf90_get_var(ncidSIC,varidSIC,sic, &
        &                start=(/1,1,tstep/),count=(/GridNX,GridNY,1/)))

    end subroutine read_file


    subroutine nf90_chkerr(iret)
        integer,intent(in) :: iret
        if (iret /= NF90_NOERR) call ERROR(nf90_strerror(iret))
    end subroutine nf90_chkerr

end module amip_forcing_mod
