!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! Three different baselining methods are offered with slightly different
! syntax. To ease the support, each baselining method is coded into its own
! file (command-baseline-*.f90) and associated module. However, the
! definition of the syntax and its parsing must be implemented here because
! the syntax of the main command and of the lineregion (lineset_or_mask)
! must be defined only once even though it is meaningful for the polynomial
! and median baselining. Once the parsing is done, the different
! combination of options is checked and then the execution is switched to
! the right file and module that contains all the details associated to
! each method.
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module cubemain_baseline
  use cubetools_parameters
  use cubetools_structure
  use cubemain_messaging
  use cubemain_baseline_cubes_types
  use cubemain_lineset_or_mask_types
  use cubemain_baseline_median
  use cubemain_baseline_chebyshev
  use cubemain_baseline_wavelet
  !
  public :: baseline
  private
  !
  integer(kind=code_k), parameter :: code_base_median  = 1
  integer(kind=code_k), parameter :: code_base_poly    = 2
  integer(kind=code_k), parameter :: code_base_wavelet = 3
  !
  type :: baseline_comm_t
     type(baseline_cubes_comm_t)     :: cubes
     type(lineset_or_mask_comm_t)    :: lineregion
     type(baseline_median_comm_t)    :: median
     type(baseline_chebyshev_comm_t) :: poly
     type(baseline_wavelet_comm_t)   :: wavelet
   contains
     procedure, public  :: register => cubemain_baseline_comm_register
     procedure, private :: parse    => cubemain_baseline_comm_parse
     procedure, private :: main     => cubemain_baseline_comm_main
  end type baseline_comm_t
  type(baseline_comm_t) :: baseline
  !
  type baseline_user_t
     integer(kind=code_k)            :: method  ! Baselining method
     type(baseline_median_user_t)    :: median  ! Median filtering parameters
     type(baseline_chebyshev_user_t) :: poly    ! Polynomial parameters
     type(baseline_wavelet_user_t)   :: wavelet ! Wavelet filtering parameters
  end type baseline_user_t
  !
contains
  !
  subroutine cubemain_baseline_command(line,error)
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    character(len=*), intent(in)    :: line
    logical,          intent(inout) :: error
    !
    type(baseline_user_t) :: user
    character(len=*), parameter :: rname='BASELINE>COMMAND'
    !
    call cubemain_message(mainseve%trace,rname,'Welcome')
    !
    call baseline%parse(line,user,error)
    if (error) return
    call baseline%main(user,error)
    if (error) return
  end subroutine cubemain_baseline_command
  !
  !----------------------------------------------------------------------
  !
  subroutine cubemain_baseline_comm_register(comm,error)
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(baseline_comm_t), intent(inout) :: comm
    logical,                intent(inout) :: error
    !
    character(len=*), parameter :: rname='BASELINE>COMM>REGISTER'
    !
    call cubemain_message(mainseve%trace,rname,'Welcome')
    !
    call comm%cubes%register(cubemain_baseline_command,error)
    if (error) return
    call comm%median%register(error)
    if (error) return
    call comm%poly%register(error)
    if (error) return
    call comm%wavelet%register(error)
    if (error) return
    call comm%lineregion%register(error)
    if (error) return
  end subroutine cubemain_baseline_comm_register
  !
  subroutine cubemain_baseline_comm_parse(comm,line,user,error)
    !----------------------------------------------------------------------
    ! 
    !----------------------------------------------------------------------
    class(baseline_comm_t), intent(inout) :: comm
    character(len=*),       intent(in)    :: line
    type(baseline_user_t),  intent(out)   :: user
    logical,                intent(inout) :: error
    !
    logical :: combined
    character(len=*), parameter :: rname='BASELINE>COMM>PARSE'
    !
    call cubemain_message(mainseve%trace,rname,'Welcome')
    !
    ! Parse the method
    call comm%median%parse_key(line,user%median,error)
    if (error) return
    call comm%poly%parse_key(line,user%poly,error)
    if (error) return
    call comm%wavelet%parse_key(line,user%wavelet,error)
    if (error) return
    ! Sanity check: Are more than one method called?
    combined = (&
         (user%median%present.and.user%poly%present).or.&
         (user%median%present.and.user%wavelet%present).or.&
           (user%poly%present.and.user%wavelet%present))
    if (combined) then
       call cubemain_message(seve%e,rname,'The /MEDIAN, /WAVELET, or /POLYNOMIAL baselining method are exclusive from each other')
       call cubemain_message(seve%e,rname,'   => Choose only one of them')
       error = .true.
       return
    endif
    !
    ! Parse the reminder of the command line depending on the use case
    if (user%median%present) then
       user%method = code_base_median
       call comm%median%parse_others(comm%cubes,comm%lineregion,line,user%median,error)
       if (error) return
    else if (user%poly%present) then
       user%method = code_base_poly
       call comm%poly%parse_others(comm%cubes,comm%lineregion,line,user%poly,error)
       if (error) return
    else if (user%wavelet%present) then
       user%method = code_base_wavelet
       call comm%wavelet%parse_others(comm%cubes,line,user%wavelet,error)
       if (error) return
    else
       ! Default to median filter
       user%method = code_base_median
       call comm%median%parse_others(comm%cubes,comm%lineregion,line,user%median,error)
       if (error) return
    endif
  end subroutine cubemain_baseline_comm_parse
  !
  subroutine cubemain_baseline_comm_main(comm,user,error) 
    use cubeadm_timing
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(baseline_comm_t), intent(in)    :: comm
    type(baseline_user_t),  intent(inout) :: user
    logical,                intent(inout) :: error
    !
    character(len=*), parameter :: rname='BASELINE>COMM>MAIN'
    !
    call cubemain_message(mainseve%trace,rname,'Welcome')
    !
    select case (user%method)
    case (code_base_median)
       call comm%median%main(user%median,error)
       if (error) return
    case (code_base_poly)
       call comm%poly%main(user%poly,error)
       if (error) return
    case (code_base_wavelet)
       call comm%wavelet%main(user%wavelet,error)
       if (error) return
    case default
       call cubemain_message(seve%e,rname,'Unknown baselining method code')
       error = .true.
       return
    end select

  end subroutine cubemain_baseline_comm_main
end module cubemain_baseline
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
