!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module cubetools_access_types
  use cubetools_parameters
  use cubetools_structure
  use cubesyntax_messaging
  !
  !***JP: The module is called cubetools_accessorder_types but the types are called order_*_t!
  !***JP: For me, it's unclear whether the /KEY IMAGE|SPECTRUM always refer to the access order.
  !***JP: It could also means produce an IMAGE or a SPECTRUM with crossed access
  !
  public :: order_comm_t,order_user_t,order_prog_t
  !
  public :: cubetools_accessname,cubetools_ordername
  public :: cubetools_order2ext,cubetools_access2ext,cubetools_access2order,cubetools_order2access
  public :: cubetools_transpose_order,cubetools_transpose_access,cubetools_transpose_operator
  private
  !
  integer(kind=4), parameter :: norders=2
  character(len=*), parameter :: orders(norders) = (/ 'IMAGE   ','SPECTRUM' /)
  !
  ! Support for /KEY IMAGE|SPECTRUM
  type :: order_comm_t
    type(option_t),      pointer :: opt
    type(keywordlist_comm_t), pointer :: arg
  contains
    procedure, public :: register => cubetools_order_comm_register
    procedure, public :: parse    => cubetools_order_comm_parse
  end type order_comm_t
  type :: order_user_t
    logical               :: do
    character(len=argu_l) :: arg
  contains
    procedure, public :: toprog => cubetools_order_user_toprog
  end type order_user_t
  type :: order_prog_t
    integer(kind=code_k) :: code
  end type order_prog_t
  !
contains
  !
  subroutine cubetools_order_comm_register(order,name,abstract,help,error)
    !-------------------------------------------------------------------
    ! 
    !-------------------------------------------------------------------
    class(order_comm_t), intent(inout) :: order
    character(len=*),    intent(in)    :: name      ! Command name
    character(len=*),    intent(in)    :: abstract  ! Command abstract
    character(len=*),    intent(in)    :: help      ! Command help
    logical,             intent(inout) :: error
    !
    type(keywordlist_comm_t) :: keyarg
    character(len=*), parameter :: rname='ORDER>COMM>REGISTER'
    !
    call cubetools_register_option(&
         name,'Order',&
         abstract,&
         help,&
         order%opt,error)
    if (error) return
    call keyarg%register( &
         'Order', &
         'Order name',  &
         strg_id,&
         code_arg_mandatory,  &
         orders, &
         .not.flexible,&
         order%arg,&
         error)
    if (error) return
  end subroutine cubetools_order_comm_register
  !
  subroutine cubetools_order_comm_parse(order,line,user,error)
    !-------------------------------------------------------------------
    ! 
    !-------------------------------------------------------------------
    class(order_comm_t), intent(in)    :: order
    character(len=*),    intent(in)    :: line
    type(order_user_t),  intent(inout) :: user
    logical,             intent(inout) :: error
    !
    character(len=*), parameter :: rname='ORDER>COMM>PARSE'
    !
    call order%opt%present(line,user%do,error)
    if (error) return
    if (user%do) then
      call cubetools_getarg(line,order%opt,1,user%arg,mandatory,error)
      if (error) return
    endif
  end subroutine cubetools_order_comm_parse
  !
  subroutine cubetools_order_user_toprog(user,order,default,prog,error)
    !-------------------------------------------------------------------
    !
    !-------------------------------------------------------------------
    class(order_user_t),  intent(in)    :: user
    type(order_comm_t),   intent(in)    :: order
    integer(kind=code_k), intent(in)    :: default
    type(order_prog_t),   intent(inout) :: prog
    logical,              intent(inout) :: error
    !
    character(len=12) :: key
    integer(kind=4) :: iorder
    character(len=*), parameter :: rname='ORDER>USER>TOPROG'
    !
    if (user%do) then
      call cubetools_keywordlist_user2prog(order%arg,user%arg,iorder,key,error)
      if (error) return
      select case (key)
      case ('IMAGE')
        prog%code = code_access_imaset
      case ('SPECTRUM')
        prog%code = code_access_speset
      case default
        call cubesyntax_message(seve%e,rname,'Unknown access')
        error = .true.
        return
      end select
    else
      prog%code = default
    endif
  end subroutine cubetools_order_user_toprog
  !
  !---------------------------------------------------------------------
  !
  function cubetools_accessname(access)
    !---------------------------------------------------------------------
    ! Return the name of the access given its code
    !---------------------------------------------------------------------
    character(len=7) :: cubetools_accessname
    integer(kind=code_k), intent(in) :: access
    !
    select case (access)
    case (code_access_imaset)
      cubetools_accessname = 'ImaSet'
    case (code_access_speset)
      cubetools_accessname = 'SpeSet'
    case (code_access_subset)
      cubetools_accessname = 'SubSet'
    case (code_access_blobset)
      cubetools_accessname = 'BlobSet'
    case (code_access_fullset)
      cubetools_accessname = 'FullSet'
    case default
      cubetools_accessname = '???'
    end select
  end function cubetools_accessname
  !
  function cubetools_ordername(order)
    !---------------------------------------------------------------------
    ! Return the name of the order given its code
    !---------------------------------------------------------------------
    character(len=6) :: cubetools_ordername
    integer(kind=code_k), intent(in) :: order
    !
    select case (order)
    case (code_cube_unkset)
      cubetools_ordername = 'UnkSet'
    case (code_cube_speset)
      cubetools_ordername = 'SpeSet'
    case (code_cube_imaset)
      cubetools_ordername = 'ImaSet'
    case default
      cubetools_ordername = '???'
    end select
  end function cubetools_ordername
  !
  function cubetools_order2ext(order)
    !---------------------------------------------------------------------
    ! Return the default extension suited for the input order mode.
    !---------------------------------------------------------------------
    character(len=exte_l) :: cubetools_order2ext
    integer(kind=code_k), intent(in) :: order
    !
    select case (order)
    case (code_cube_imaset)
       cubetools_order2ext = '.lmv'
    case (code_cube_speset)
       cubetools_order2ext = '.vlm'
    case default
       cubetools_order2ext = '.unk'
    end select
  end function cubetools_order2ext
  !
  function cubetools_access2ext(access)
    !---------------------------------------------------------------------
    ! Return the default extension suited for the input access mode.
    !---------------------------------------------------------------------
    character(len=exte_l) :: cubetools_access2ext
    integer(kind=4), intent(in) :: access
    !
    select case (access)
    case (code_access_imaset)
       cubetools_access2ext = '.lmv'
    case (code_access_speset)
       cubetools_access2ext = '.vlm'
    case default
       cubetools_access2ext = '.unk'
    end select
  end function cubetools_access2ext
  !
  function cubetools_access2order(access)
    !--------------------------------------------------------------------- 
    ! Return the order suited for the input access mode.
    !---------------------------------------------------------------------
    integer(kind=4) :: cubetools_access2order
    integer(kind=4), intent(in) :: access  ! code_access_*
    !
    select case (access)
    case (code_access_imaset)
       cubetools_access2order = code_cube_imaset
    case (code_access_speset)
       cubetools_access2order = code_cube_speset
    case default
       cubetools_access2order = code_null
    end select
  end function cubetools_access2order
  !
  function cubetools_order2access(order)
    use cubetools_parameters
    !---------------------------------------------------------------------
    ! Return the access mode suited for the input order.
    !---------------------------------------------------------------------
    integer(kind=4) :: cubetools_order2access  ! code_cube_*
    integer(kind=4), intent(in) :: order
    !
    select case (order)
    case (code_cube_imaset)
       cubetools_order2access = code_access_imaset
    case (code_cube_speset)
       cubetools_order2access = code_access_speset
    case (code_cube_unkset)
       cubetools_order2access = code_access_any
    case default
       cubetools_order2access = code_null
    end select
  end function cubetools_order2access
  !
  !------------------------------------------------------------------------
  !
  function cubetools_transpose_order(code_order)
    !----------------------------------------------------------------------
    ! Transpose the data order:  LMV <-> VLM
    !----------------------------------------------------------------------
    integer(kind=4)             :: cubetools_transpose_order
    integer(kind=4), intent(in) :: code_order
    !
    select case (code_order)
    case (code_cube_imaset)
      cubetools_transpose_order = code_cube_speset
    case (code_cube_speset)
      cubetools_transpose_order = code_cube_imaset
    case default
      cubetools_transpose_order = code_null
    end select
    !
  end function cubetools_transpose_order
  !
  function cubetools_transpose_access(code_access)
    !----------------------------------------------------------------------
    ! Transpose the data access mode: spectrum <-> image
    !----------------------------------------------------------------------
    integer(kind=4)             :: cubetools_transpose_access  ! code_access_*
    integer(kind=4), intent(in) :: code_access                 ! code_access_*
    !
    select case (code_access)
    case (code_access_imaset)
      cubetools_transpose_access = code_access_speset
    case (code_access_speset)
      cubetools_transpose_access = code_access_imaset
    case default
      cubetools_transpose_access = code_null
    end select
    !
  end function cubetools_transpose_access
  !
  subroutine cubetools_transpose_operator(inorder,ouorder,operator,error)
    !----------------------------------------------------------------------
    ! 
    !----------------------------------------------------------------------
    integer(kind=4),         intent(in)    :: inorder
    integer(kind=4),         intent(in)    :: ouorder
    character(len=trop_l),   intent(out)   :: operator
    logical,                 intent(inout) :: error
    !
    character(len=mess_l) :: mess
    character(len=*), parameter  :: rname='TRANSPOSE>OPERATOR'
    !
    if (inorder.eq.code_cube_imaset .and.  &
        ouorder.eq.code_cube_speset) then
       operator = '312'
    elseif (inorder.eq.code_cube_speset .and.  &
            ouorder.eq.code_cube_imaset) then
       operator = '231'
    else
       write(mess,'(2(a,i0))')  &
         'Do not know how to transpose from code ',inorder,' to code ',ouorder
       call cubesyntax_message(seve%e,rname,mess)
       error = .true.
       return
    endif
    !  
  end subroutine cubetools_transpose_operator
end module cubetools_access_types
! 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
