module opt_prop_lbl

  use dc_types
  use gtool_history

  implicit none

  private

  public :: OptPropInitCore
  public :: OptPropFinalizeCore
  public :: OptPropGetNWNCore
  public :: OptPropGetNPressCore
  public :: OptPropGetNMolCore
  public :: OptPropGetDelWNCore
  public :: OptPropGetWNCore
  public :: OptPropGetAbsCoefProfCore
  public :: OptPropGetPFIntedCore
  public :: OptPropGetPFIntedRatioCore


  character(128)       , save :: OptPropNcFNSave
  integer              , save :: NPressSave
  integer              , save :: NMolSave
  integer              , save :: NWaveNumSave
  real(DP), allocatable, save :: w_WaveNumSave(:)
!!$  real(DP), allocatable, save :: pmw_LBLAbsCoef(:,:,:)

  character(128), save :: AbsCoefVarName = 'rmw_TAbsorpK'
  character(128), save :: PFRatioVarName = 'ra_PFRatio'

  character(128), save :: ModuleName = 'opt_prop_lbl'

  logical, save :: FlagInited = .false.

contains

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

  subroutine OptPropInitCore( &
    & OptPropNcFN &
    & )

    use rad_utils, only : InqDimLength


    character(*), intent(in) :: OptPropNcFN


    ! local variables
    !


!!$    if ( .not. FlagInited ) then
!!$      write( 6, * ) trim( ModuleName ), " is not initialized."
!!$      stop
!!$    end if


    OptPropNcFNSave = OptPropNcFN

    NPressSave = InqDimLength( OptPropNcFNSave, 'r_Press'   )
    NMolSave   = InqDimLength( OptPropNcFNSave, 'm_MolNum'  )
    NWaveNumSave    = InqDimLength( OptPropNcFNSave, 'w_WaveNum' )

    allocate( w_WaveNumSave  ( 1:NWaveNumSave ) )
!!$    allocate( pmw_LBLAbsCoef( 1:NPressSave, 1:NMolSave, 1:NWaveNumSave ) )

    call HistoryGet( OptPropNcFNSave, 'w_WaveNum'   , w_WaveNumSave  , quiet = .true. )
!!$    call HistoryGet( OptPropNcFNSave, AbsCoefVarName, pmw_LBLAbsCoef, quiet = .true. )


    FlagInited = .true.

  end subroutine OptPropInitCore

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

  subroutine OptPropFinalizeCore


    ! local variables
    !


    if ( .not. FlagInited ) then
      write( 6, * ) trim( ModuleName ), " is not initialized."
      stop
    end if

    NPressSave = 0
    NMolSave   = 0
    NWaveNumSave    = 0

    if ( allocated( w_WaveNumSave ) ) then
      deallocate( w_WaveNumSave )
    end if
!!$    if ( allocated( pmw_LBLAbsCoef ) ) then
!!$      deallocate( pmw_LBLAbsCoef )
!!$    end if


    FlagInited = .false.

  end subroutine OptPropFinalizeCore

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

  function OptPropGetNWNCore() result( NWN )


    integer :: NWN

    ! local variables
    !


    if ( .not. FlagInited ) then
      write( 6, * ) trim( ModuleName ), " is not initialized."
      stop
    end if


    NWN = NWaveNumSave


  end function OptPropGetNWNCore

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

  function OptPropGetNPressCore() result( NPress )


    integer :: NPress

    ! local variables
    !


    if ( .not. FlagInited ) then
      write( 6, * ) trim( ModuleName ), " is not initialized."
      stop
    end if


    NPress = NPressSave


  end function OptPropGetNPressCore

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

  function OptPropGetNMolCore() result( NMol )


    integer :: NMol

    ! local variables
    !


    if ( .not. FlagInited ) then
      write( 6, * ) trim( ModuleName ), " is not initialized."
      stop
    end if


    NMol = NMolSave


  end function OptPropGetNMolCore

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

  function OptPropGetDelWNCore() result( DelWaveNum )


    real(DP) :: DelWaveNum

    ! local variables
    !


    if ( .not. FlagInited ) then
      write( 6, * ) trim( ModuleName ), " is not initialized."
      stop
    end if


    DelWaveNum = w_WaveNumSave( 2 ) - w_WaveNumSave( 1 )


  end function OptPropGetDelWNCore

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

  function OptPropGetWNCore( iWaveNum ) result( WaveNum )


    integer, intent(in) :: iWaveNum

    real(DP) :: WaveNum

    ! local variables
    !


    if ( .not. FlagInited ) then
      write( 6, * ) trim( ModuleName ), " is not initialized."
      stop
    end if


    WaveNum = w_WaveNumSave( iWaveNum )


  end function OptPropGetWNCore

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

  subroutine OptPropGetAbsCoefProfCore( &
    & iWaveNum, NPress, NMol, &
    & zm_AbsCoef &
    & )

    use rad_utils, only : MkRangeString


    integer     , intent(in ) :: iWaveNum
    integer     , intent(in ) :: NPress
    integer     , intent(in ) :: NMol
    real(DP)    , intent(out) :: zm_AbsCoef(1:NPress,1:NMol)


    ! local variables
    !
    character(128) :: String


    if ( .not. FlagInited ) then
      write( 6, * ) trim( ModuleName ), " is not initialized."
      stop
    end if


    String = MkRangeString( "w_WaveNum", iWaveNum )

    call HistoryGet( OptPropNcFNSave, AbsCoefVarName, zm_AbsCoef, &
      & range = string, quiet = .true. )

  end subroutine OptPropGetAbsCoefProfCore

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

  subroutine OptPropGetPFIntedCore( &
    & iWaveNum, &
    & kmax, &
    & r_Temp, SurfTemp, &
    & r_PFInted, SurfPFInted, SurfDPFDTInted &
    & )

    use constants0, only : PI

    use planck_func_wrapper

    integer , intent(in ) :: iWaveNum
    integer , intent(in ) :: kmax
    real(DP), intent(in ) :: r_Temp(0:kmax)
    real(DP), intent(in ) :: SurfTemp
    real(DP), intent(out) :: r_PFInted  (0:kmax)
    real(DP), intent(out) :: SurfPFInted
    real(DP), intent(out) :: SurfDPFDTInted


    ! local variables
    !
    real(DP) :: WaveNum
    real(DP) :: DelWaveNum
    real(DP) :: WNs
    real(DP) :: WNe
    integer  :: GQNum


    WaveNum    = OptPropGetWNCore( iWaveNum )
    DelWaveNum = OptPropGetDelWNCore()

    WNs = WaveNum - DelWaveNum / 2.0d0
    WNe = WaveNum + DelWaveNum / 2.0d0
!!$    GQNum = 1
    GQNum = int( DelWaveNum / 10.0d0 ) + 1
    !
    call Integ_PF_GQ_Array1D( &
      & WNs, WNe, GQNum, &
      & 0, kmax, &
      & r_Temp, &
      & r_PFInted &
      & )
    r_PFInted = PI * r_PFInted
    call Integ_PF_GQ_Array0D( &
      & WNs, WNe, GQNum, &
      & SurfTemp, &
      & SurfPFInted &
      & )
    SurfPFInted = PI * SurfPFInted
    call Integ_DPFDT_GQ_Array0D( &
      & WNs, WNe, GQNum,                 & ! (in )
      & SurfTemp,                & ! (in )
      & SurfDPFDTInted                  & ! (out)
      & )
    SurfDPFDTInted = PI * SurfDPFDTInted


  end subroutine OptPropGetPFIntedCore

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

  subroutine OptPropGetPFIntedRatioCore( &
    & iWaveNum, NPress, &
    & z_PFRatio, SurfPFRatio &
    & )

    use rad_utils, only : MkRangeString


    integer     , intent(in ) :: iWaveNum
    integer     , intent(in ) :: NPress
    real(DP)    , intent(out) :: z_PFRatio(1:NPress)
    real(DP)    , intent(out) :: SurfPFRatio


    ! local variables
    !
    character(128) :: String

!!$    real(DP), allocatable :: za_PFRatio(:,:)


    if ( .not. FlagInited ) then
      write( 6, * ) trim( ModuleName ), " is not initialized."
      stop
    end if


!!$    String = MkRangeString( "w_WaveNum", iWaveNum )
    String = MkRangeString( "BinNum", iWaveNum )

    call HistoryGet( OptPropNcFNSave, PFRatioVarName, z_PFRatio, &
      & range = string, quiet = .true. )


!!$    allocate( za_PFRatio( NPressSave, NWaveNumSave ) )
!!$    call HistoryGet( OptPropNcFNSave, PFRatioVarName, za_PFRatio, &
!!$      & quiet = .true. )
!!$    z_PFRatio = za_PFRatio(:,iWaveNum)
!!$    deallocate( za_PFRatio )


    SurfPFRatio = z_PFRatio(1)


  end subroutine OptPropGetPFIntedRatioCore

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

end module opt_prop_lbl
