module opt_prop_lbl

  use dc_types
  use gtool_history

  implicit none

  private

  public :: OptPropLBLInit
  public :: OptPropLBLFinalize
  public :: OptPropLBLGetNWN
  public :: OptPropLBLGetNPress
  public :: OptPropLBLGetNMol
  public :: OptPropLBLGetDelWN
  public :: OptPropLBLGetWN
  public :: OptPropLBLGetAbsCoefProf
  public :: OptPropLBLGetPFInted
  public :: OptPropLBLGetPFIntedRatio


  character(128)       , save :: LBLOptPropNcFN
  integer              , save :: LBLNPress
  integer              , save :: LBLNMol
  integer              , save :: LBLNWN
  real(DP), allocatable, save :: w_LBLWaveNum(:)
!!$  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 OptPropLBLInit( &
    & OptPropNcFN &
    & )

    use utils, only : InqDimLength


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


    ! local variables
    !


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


    LBLOptPropNcFN = OptPropNcFN

    LBLNPress = InqDimLength( LBLOptPropNcFN, 'r_Press'   )
    LBLNMol   = InqDimLength( LBLOptPropNcFN, 'm_MolNum'  )
    LBLNWN    = InqDimLength( LBLOptPropNcFN, 'w_WaveNum' )

    allocate( w_LBLWaveNum  ( 1:LBLNWN ) )
!!$    allocate( pmw_LBLAbsCoef( 1:LBLNPress, 1:LBLNMol, 1:LBLNWN ) )

    call HistoryGet( LBLOptPropNcFN, 'w_WaveNum'   , w_LBLWaveNum  , quiet = .true. )
!!$    call HistoryGet( LBLOptPropNcFN, AbsCoefVarName, pmw_LBLAbsCoef, quiet = .true. )


    FlagInited = .true.

  end subroutine OptPropLBLInit

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

  subroutine OptPropLBLFinalize


    ! local variables
    !


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

    LBLNPress = 0
    LBLNMol   = 0
    LBLNWN    = 0

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


    FlagInited = .false.

  end subroutine OptPropLBLFinalize

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

  function OptPropLBLGetNWN() result( NWN )


    integer :: NWN

    ! local variables
    !


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


    NWN = LBLNWN


  end function OptPropLBLGetNWN

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

  function OptPropLBLGetNPress() result( NPress )


    integer :: NPress

    ! local variables
    !


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


    NPress = LBLNPress


  end function OptPropLBLGetNPress

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

  function OptPropLBLGetNMol() result( NMol )


    integer :: NMol

    ! local variables
    !


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


    NMol = LBLNMol


  end function OptPropLBLGetNMol

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

  function OptPropLBLGetDelWN() result( DelWaveNum )


    real(DP) :: DelWaveNum

    ! local variables
    !


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


    DelWaveNum = w_LBLWaveNum( 2 ) - w_LBLWaveNum( 1 )


  end function OptPropLBLGetDelWN

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

  function OptPropLBLGetWN( 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_LBLWaveNum( iWaveNum )


  end function OptPropLBLGetWN

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

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

    use 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( LBLOptPropNcFN, AbsCoefVarName, zm_AbsCoef, &
      & range = string, quiet = .true. )

  end subroutine OptPropLBLGetAbsCoefProf

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

  subroutine OptPropLBLGetPFInted( &
    & 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    = OptPropLBLGetWN( iWaveNum )
    DelWaveNum = OptPropLBLGetDelWN()

    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 OptPropLBLGetPFInted

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

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

    use 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( LBLOptPropNcFN, PFRatioVarName, z_PFRatio, &
      & range = string, quiet = .true. )


!!$    allocate( za_PFRatio( LBLNPress, LBLNWN ) )
!!$    call HistoryGet( LBLOptPropNcFN, PFRatioVarName, za_PFRatio, &
!!$      & quiet = .true. )
!!$    z_PFRatio = za_PFRatio(:,iWaveNum)
!!$    deallocate( za_PFRatio )


    SurfPFRatio = z_PFRatio(1)


  end subroutine OptPropLBLGetPFIntedRatio

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

end module opt_prop_lbl
