module ac_io_module

  use vtype_module
  use ni3_module
  use netcdf

  implicit none

  private

  public :: ac_io_output_init
  public :: ac_io_output_end
  public :: ac_io_output
  public :: ac_io_input_init
  public :: ac_io_input_end
  public :: ac_io_input_axisetc
  public :: ac_io_input

  integer          , save :: OutNcID
  integer          , save :: InNcID

  !----------------------------------------------------------------------------

contains

  !----------------------------------------------------------------------------

  subroutine ac_io_output_init( &
    & FileName, NMolNum, m_MolNum, NLev, p_Press, pm_VMR, p_Temp, DelWaveNum &
    & )


    character(*), intent(in ) :: FileName
    integer     , intent(in ) :: NMolNum
    integer     , intent(in ) :: m_MolNum( NMolNum )
    integer     , intent(in ) :: NLev
    real(dp)    , intent(in ) :: p_Press( NLev )
    real(dp)    , intent(in ) :: pm_VMR( NLev, NMolNum )
    real(dp)    , intent(in ) :: p_Temp( NLev )
    real(dp)    , intent(in ) :: DelWaveNum


    !
    ! local variables
    !
    integer(i4b)         , parameter :: ndims1 = 1
    character(len=extstr)            :: dname1( ndims1 )
    integer(i4b)         , parameter :: ndims2 = 2
    character(len=extstr)            :: dname2( ndims2 )
    integer(i4b)         , parameter :: ndims3 = 3
    character(len=extstr)            :: dname3( ndims3 )
    character(len=extstr)            :: name, stdname, units


    call ni3_open( FileName, "new", OutNcID )

    call ni3_put_att( OutNcID, "_global_", "comment_dwn_m-1", DelWaveNum )

    name     = "MolNum"
    stdname  = "MolNum"
    units    = "1"
    call ni3_set_dim( OutNcID, name, NF90_INT   , m_MolNum, &
      & stdname = stdname, units  = units )
    name    = "Press"
    stdname = "plev"
    units   = "Pa"
    call ni3_set_dim( OutNcID, name, NF90_DOUBLE, p_Press  , &
      & stdname = stdname, units  = units )
    name    = "WaveNum"
    stdname = "wavenumber"
    units   = "m-1"
!!$    call ni3_def_dim( OutNcID, name, NF90_DOUBLE, nwn , &
    call ni3_def_dim( OutNcID, name, NF90_DOUBLE, 0 , &
      & stdname = stdname, units  = units )


    dname1( 1 ) = "Press"

    name    = "Temp"
    stdname = "air_temperature"
    units   = "K"
    call ni3_def_var( OutNcID, name, NF90_DOUBLE, ndims1, dname1, &
      & stdname = stdname, units = units )
    call ni3_put_var( OutNcID, name, p_Temp )


    dname2( 1 ) = "Press"
    dname2( 2 ) = "MolNum"

    name    = "VMR"
    stdname = "volume mixing ratio"
    units   = "1"
    call ni3_def_var( OutNcID, name, NF90_DOUBLE, ndims2, dname2, &
      & stdname = stdname, units = units )
    call ni3_put_var( OutNcID, name, pm_VMR )


    dname3( 1 ) = "Press"
    dname3( 2 ) = "MolNum"
    dname3( 3 ) = "WaveNum"

    name    = "AbsCoef"
    stdname = "absorption_coefficient"
!!$    units   = "(kg m-2)-1"
      units   = "(molecule m-2)-1"
    call ni3_def_var( OutNcID, name, NF90_DOUBLE, ndims3, dname3, &
      & stdname = stdname, units = units )

!!$    name    = "AbsCoefLine"
!!$    stdname = "line_absorption_coefficient"
!!$!    units   = "(kg m-2)-1"
!!$      units   = "(molecule m-2)-1"
!!$    call ni3_def_var( OutNcID, name, NF90_DOUBLE, ndims3, dname3, &
!!$      & stdname = stdname, units = units )
!!$
!!$    name    = "AbsCoefCont"
!!$    stdname = "continuum_absorption_coefficient"
!!$!    units   = "(kg m-2)-1"
!!$      units   = "(molecule m-2)-1"
!!$    call ni3_def_var( OutNcID, name, NF90_DOUBLE, ndims3, dname3, &
!!$      & stdname = stdname, units = units )


  end subroutine ac_io_output_init

  !----------------------------------------------------------------------------

  subroutine ac_io_output_end


    call ni3_close( OutNcID )


  end subroutine ac_io_output_end

  !----------------------------------------------------------------------------

  subroutine ac_io_output( &
    & IMol, kLev, nwnsl, VarName, wn, ac, iwnsls, iwnsle, iwnl, FlagOutputWN &
    & )


    integer(i4b), intent(in ) :: IMol
    integer(i4b), intent(in ) :: kLev
    integer(i4b), intent(in ) :: nwnsl
    character(*), intent(in ) :: VarName
    real(dp)    , intent(in ) :: wn( nwnsl )
    real(dp)    , intent(in ) :: ac( nwnsl )
    integer(i4b), intent(in ) :: iwnsls
    integer(i4b), intent(in ) :: iwnsle
    integer(i4b), intent(in ) :: iwnl
    logical     , intent(in ) :: FlagOutputWN


    !
    ! local variables
    !
    character(len=extstr)       :: name
    integer(i4b)                :: varid_wn
    integer(i4b)                :: varid_ac
    integer(i4b)                :: istatus
    character(len=extstr)       :: err_mes = "in ac_io_output"
    integer(i4b)                :: st1( 1 ), co1( 1 ), st3( 3 ), co3( 3 )


    name = "WaveNum"
    call ni3_inq_var( OutNcID, name, varid_wn )
!!$    name = "AbsCoef"
    name = VarName
    call ni3_inq_var( OutNcID, name, varid_ac )
    call ni3_enddef( OutNcID )


    if ( FlagOutputWN ) then
      st1( 1 ) = iwnl + iwnsls - 1
      co1( 1 ) = iwnsle - iwnsls + 1
      istatus = nf90_put_var( OutNcID, varid_wn, wn, start = st1, count = co1 )
      call ni3_handle_err( istatus, err_mes )
    end if


    st3( 1 ) = kLev
    st3( 2 ) = IMol
    st3( 3 ) = iwnl + iwnsls - 1
    co3( 1 ) = 1
    co3( 2 ) = 1
    co3( 3 ) = iwnsle - iwnsls + 1
    istatus = nf90_put_var( OutNcID, varid_ac, ac, start = st3, count = co3 )
    call ni3_handle_err( istatus, err_mes )


    call ni3_redef( OutNcID )
    call ni3_enddef( OutNcID )


  end subroutine ac_io_output

  !----------------------------------------------------------------------------
!!$
!!$  subroutine ac_io_wnsize( len )
!!$
!!$
!!$    integer(i4b), intent(out) :: len
!!$
!!$
!!$    !
!!$    ! local variables
!!$    !
!!$
!!$
!!$    call ni3_inq_dimlen( NcIDAC, "wn", len )
!!$
!!$
!!$  end subroutine ac_io_wnsize
!!$
  !----------------------------------------------------------------------------
!!$
!!$  subroutine ac_io_readwn( nwnsl, wn )
!!$
!!$
!!$    integer(i4b), intent(in ) :: nwnsl
!!$    real(dp)    , intent(out) :: wn( nwnsl )
!!$
!!$
!!$    !
!!$    ! local variables
!!$    !
!!$
!!$
!!$    call ni3_get_var( NcIDAC, "wn", wn )
!!$
!!$
!!$  end subroutine ac_io_readwn
!!$
  !----------------------------------------------------------------------------

  subroutine ac_io_input_init( &
    & FileName, NMolNum, NLev, NWN &
    & )


    character(*), intent(in ) :: FileName
    integer     , intent(out) :: NMolNum
    integer     , intent(out) :: NLev
    integer     , intent(out) :: nwn


    !
    ! local variables
    !
    character(len=extstr)            :: name


    call ni3_open( FileName, "read", InNcID )

    name     = "MolNum"
    call ni3_inq_dimlen( InNcID, name, NMolNum )

    name    = "Press"
    call ni3_inq_dimlen( InNcID, name, NLev )

    name    = "WaveNum"
    call ni3_inq_dimlen( InNcID, name, NWN )


  end subroutine ac_io_input_init

  !----------------------------------------------------------------------------

  subroutine ac_io_input_end


    call ni3_close( InNcID )


  end subroutine ac_io_input_end

  !----------------------------------------------------------------------------

  subroutine ac_io_input_axisetc( &
    & NMolNum, NLev, &
    & m_MolNum, p_Press, pm_VMR, p_Temp &
    & )


    integer     , intent(in ) :: NMolNum
    integer     , intent(in ) :: NLev
    integer     , intent(out) :: m_MolNum( NMolNum )
    real(dp)    , intent(out) :: p_Press( NLev )
    real(dp)    , intent(out) :: pm_VMR( NLev, NMolNum )
    real(dp)    , intent(out) :: p_Temp( NLev )


    !
    ! local variables
    !
    character(len=extstr)            :: name
!!$    character(len=extstr)            :: stdname, units


    name     = "MolNum"
    call ni3_get_var( InNcID, name, m_MolNum )

    name    = "Press"
    call ni3_get_var( InNcID, name, p_Press )

    name    = "Temp"
    call ni3_get_var( InNcID, name, p_Temp )

    name    = "VMR"
    call ni3_get_var( InNcID, name, pm_VMR )


  end subroutine ac_io_input_axisetc

  !----------------------------------------------------------------------------

  subroutine ac_io_input( &
    & IMol, kLev, nwnsl, VarName, wn, ac, iwnsls, iwnsle, iwnl &
    & )


    integer(i4b), intent(in ) :: IMol
    integer(i4b), intent(in ) :: kLev
    integer(i4b), intent(in ) :: nwnsl
    character(*), intent(in ) :: VarName
    real(dp)    , intent(out) :: wn( nwnsl )
    real(dp)    , intent(out) :: ac( nwnsl )
    integer(i4b), intent(in ) :: iwnsls
    integer(i4b), intent(in ) :: iwnsle
    integer(i4b), intent(in ) :: iwnl


    !
    ! local variables
    !
    character(len=extstr)       :: name
    integer(i4b)                :: varid_wn
    integer(i4b)                :: varid_ac
    integer(i4b)                :: istatus
    character(len=extstr)       :: err_mes = "in ac_io_output"
    integer(i4b)                :: st1( 1 ), co1( 1 ), st3( 3 ), co3( 3 )


    name = "WaveNum"
    call ni3_inq_var( InNcID, name, varid_wn )
!!$    name = "AbsCoef"
    name = VarName
    call ni3_inq_var( InNcID, name, varid_ac )
    call ni3_enddef( InNcID )


    st1( 1 ) = iwnl + iwnsls - 1
    co1( 1 ) = iwnsle - iwnsls + 1
    istatus = nf90_get_var( InNcID, varid_wn, wn, start = st1, count = co1 )
    call ni3_handle_err( istatus, err_mes )


    st3( 1 ) = kLev
    st3( 2 ) = IMol
    st3( 3 ) = iwnl + iwnsls - 1
    co3( 1 ) = 1
    co3( 2 ) = 1
    co3( 3 ) = iwnsle - iwnsls + 1
    istatus = nf90_get_var( InNcID, varid_ac, ac, start = st3, count = co3 )
    call ni3_handle_err( istatus, err_mes )


  end subroutine ac_io_input

  !----------------------------------------------------------------------------
!!$
!!$  subroutine ac_io_readac( nwnsl, wn, ac, k, iras, iwnsls, iwnsle, iwnl )
!!$
!!$
!!$    integer(i4b), intent(in ) :: nwnsl
!!$    real(dp)    , intent(out) :: wn( nwnsl ), ac( nwnsl )
!!$    integer(i4b), intent(in ) :: k, iras, iwnsls, iwnsle, iwnl
!!$
!!$
!!$    !
!!$    ! local variables
!!$    !
!!$    real(dp)                    :: l_ac( nwnsl, 1, 1 )
!!$    character(len=extstr)       :: name
!!$    integer(i4b)         , save :: varid_wn, varid_ac
!!$    integer(i4b)                :: istatus
!!$    character(len=extstr)       :: err_mes = "in ac_io_output"
!!$    integer(i4b)                :: st1( 1 ), co1( 1 ), st3( 3 ), co3( 3 )
!!$    logical              , save :: sw_fs
!!$    data sw_fs /.true./
!!$
!!$
!!$    if( sw_fs ) then
!!$      name = "wn"
!!$      call ni3_inq_var( InNcID, name, varid_wn )
!!$      name = "ac"
!!$      call ni3_inq_var( InNcID, name, varid_ac )
!!$      call ni3_enddef( InNcID )
!!$      sw_fs = .false.
!!$    end if
!!$
!!$
!!$    st1( 1 ) = iwnl   + iwnsls - 1
!!$    co1( 1 ) = iwnsle - iwnsls + 1
!!$    istatus = nf90_get_var( InNcID, varid_wn, wn , start = st1, count = co1 )
!!$    call ni3_handle_err( istatus, err_mes )
!!$
!!$
!!$    st3( 1 ) = iwnl   + iwnsls - 1
!!$    st3( 2 ) = k
!!$    st3( 3 ) = iras
!!$    co3( 1 ) = iwnsle - iwnsls + 1
!!$    co3( 2 ) = 1
!!$    co3( 3 ) = 1
!!$    istatus = nf90_get_var( InNcID, varid_ac, l_ac, start = st3, count = co3 )
!!$    call ni3_handle_err( istatus, err_mes )
!!$
!!$
!!$    ac( : ) = l_ac( :, 1, 1 )
!!$
!!$
!!$  end subroutine ac_io_readac
!!$
  !----------------------------------------------------------------------------

end module ac_io_module
