!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module cubetools_parameters
  !--- Type lengths ---------------------------------------------------
  use gildas_def
  use gbl_message
  integer(kind=4), parameter :: inte_k=4            ! [integer] Generic integer*4
  integer(kind=4), parameter :: long_k=8            ! [integer] Generic integer*8
  integer(kind=4), parameter :: argu_k=4            ! [integer] Argument
  integer(kind=4), parameter :: code_k=4            ! [integer] Codes
  integer(kind=4), parameter :: ndim_k=4            ! [integer] Number of dimensions
  integer(kind=4), parameter :: wind_k=4            ! [integer] Number of windows
  integer(kind=4), parameter :: rang_k=4            ! [integer] Number of ranges
  integer(kind=4), parameter :: indx_k=index_length ! [integer] Index (either pixel or channel)
  integer(kind=4), parameter :: entr_k=indx_k       ! [integer] Entry
  integer(kind=4), parameter :: chan_k=indx_k       ! [integer] Channel
  integer(kind=4), parameter :: pixe_k=indx_k       ! [integer] Pixel
  integer(kind=4), parameter :: data_k=size_length  ! [integer] Data
  !
  integer(kind=4), parameter :: real_k=4 ! [real] Generic real*4
  integer(kind=4), parameter :: dble_k=8 ! [real] Generic real*8
  integer(kind=4), parameter :: sign_k=4 ! [real] Signal
  integer(kind=4), parameter :: equi_k=4 ! [real] Equinox
  integer(kind=4), parameter :: beam_k=4 ! [real] Resolution
  integer(kind=4), parameter :: coor_k=8 ! [real] Coordinate
  integer(kind=4), parameter :: tole_k=8 ! [real] Consistency tolerance
  !
  integer(kind=4), parameter :: strg_l=64                 ! [character] For string arrays
  integer(kind=4), parameter :: clin_l=commandline_length ! [character] Command line
  integer(kind=4), parameter :: varn_l=varname_length     ! [character] Variable name
  integer(kind=4), parameter :: mess_l=message_length     ! [character] Message
  integer(kind=4), parameter :: file_l=filename_length    ! [character] Directory or full path to files
  integer(kind=4), parameter :: base_l=128                ! [character] File base name or name+extension (w/o path)
  integer(kind=4), parameter :: exte_l=32                 ! [character] File name extension
  integer(kind=4), parameter :: argu_l=64                 ! [character] Argument
  integer(kind=4), parameter :: unit_l=12                 ! [character] Unit 
  integer(kind=4), parameter :: line_l=12                 ! [character] Line 
  integer(kind=4), parameter :: fram_l=12                 ! [character] Spatial or spectral Frame 
  integer(kind=4), parameter :: sour_l=12                 ! [character] Source
  integer(kind=4), parameter :: tele_l=12                 ! [character] Telescope name
  integer(kind=4), parameter :: sexa_l=12                 ! [character] Sexagesimal length
  integer(kind=4), parameter :: conv_l=12                 ! [character] Convention length
  integer(kind=4), parameter :: tagn_l=12                 ! [character] tagname length
  integer(kind=4), parameter :: name_l=16                 ! [character] array name
  integer(kind=4), parameter :: trop_l=3                  ! [character] Transposition operator
  !
  ! --- unknown -------------------------------------------------------
  character(len=*), parameter :: blankstr = ''
  character(len=*), parameter :: strg_unk = 'Unknown'
  character(len=*), parameter :: strg_emp = 'Empty'
  character(len=1), parameter :: strg_cr = char(10)  ! ASCII carriage return
  character(len=*), parameter :: strg_bl = strg_cr//strg_cr  ! Blank line helper
  integer(kind=code_k),  parameter :: code_unk = 0
  integer(kind=code_k),  parameter :: code_abs = -1
  !
  ! --- Velocity convention ------------------------------------------
  integer(kind=code_k), parameter :: code_rad = 1
  integer(kind=code_k), parameter :: code_opt = 2  
  !
  ! --- Dimensions ----------------------------------------------------
  integer(kind=ndim_k), parameter :: maxdim = 7
  integer(kind=indx_k), parameter :: code_indx_auto = huge(0_indx_k)  ! Flag for uninitialized/automatic index
  !
  ! --- Convert orders ------------------------------------------------
  integer(kind=code_k), parameter :: code_ref = 1
  integer(kind=code_k), parameter :: code_val = 2
  integer(kind=code_k), parameter :: code_inc = 3
  !
  ! --- Axis types -----------------------------------------------------
  integer(kind=code_k), parameter :: code_spa = 1
  integer(kind=code_k), parameter :: code_vel = 2
  integer(kind=code_k), parameter :: code_fre = 3
  !
  ! --- Cube orders (intrinsic data order) -----------------------------
  integer(code_k), parameter :: code_cube_unkset=100   ! Unknown cube set
  integer(code_k), parameter :: code_cube_imaset=101   ! e.g. .lmv
  integer(code_k), parameter :: code_cube_speset=102   ! e.g. .vlm
  integer(code_k), parameter :: code_table_imaset=103  ! e.g. .bat
  integer(code_k), parameter :: code_table_speset=104  ! e.g. .tab
  !
  ! --- Access modes (programmer requested accesses) -------------------
  integer(code_k), parameter :: code_access_imaset=code_cube_imaset
  integer(code_k), parameter :: code_access_speset=code_cube_speset
  integer(code_k), parameter :: code_access_subset=203            ! Sub-cubes (order does not matter)
  integer(code_k), parameter :: code_access_blobset=204           ! Collection of bits (order does not matter)
  integer(code_k), parameter :: code_access_fullset=205           ! Full cubes (order does not matter)
  ! Aliases resolved depending on the cube or user at runtime:
  integer(code_k), parameter :: code_access_imaset_or_speset=206  ! Any of the 2 unambiguous orders (imaset/speset)
  integer(code_k), parameter :: code_access_any=207               ! Any of the 3 basic orders (imaset/speset/unkset)
  integer(code_k), parameter :: code_access_user=208              ! Access resolved from context e.g. user inputs
  !
  ! --- Actions --------------------------------------------------------
  ! Read codes (for old cubes). Order matters.
  integer(code_k), parameter :: code_read_none = 10  ! Nothing needed
  integer(code_k), parameter :: code_read_head = 11  ! Header only
  integer(code_k), parameter :: code_read      = 12  ! Header + data
  integer(code_k), parameter :: code_update    = 13  ! Header + data in read-write
  ! Write codes (for new cubes)
  integer(code_k), parameter :: code_write     = 20  ! Header + data
  !
  ! --- Data buffering -------------------------------------------------
  integer(kind=4), parameter :: mbuffering = 4
  character(len=*), parameter :: buffering(mbuffering) =  &
    (/ 'AUTO  ','NONE  ','MEMORY','DISK  ' /)
  integer(code_k), parameter :: code_buffer_auto   = 1
  integer(code_k), parameter :: code_buffer_none   = 2
  integer(code_k), parameter :: code_buffer_memory = 3
  integer(code_k), parameter :: code_buffer_disk   = 4
  !
  ! --- Patch Bval/Eval to NaN -----------------------------------------
  integer(kind=4), parameter :: mpatchblank=2
  character(len=*), parameter :: patchblank(mpatchblank) =  &
    (/ 'ERROR     ','ONTHEFLY  ' /)
  integer(code_k), parameter :: code_patchblank_err = 1
  integer(code_k), parameter :: code_patchblank_otf = 2
  !
  ! --- Default index --------------------------------------------------
  integer(kind=4), parameter :: mindex=2
  character(len=*), parameter :: indexname(mindex) =  &
    (/ 'DAG    ','CURRENT' /)
  integer(code_k), parameter :: code_index_dag     = 1
  integer(code_k), parameter :: code_index_current = 2
  !
  ! --- Arguments ------------------------------------------------------
  logical, parameter ::   flexible = .true.
  logical, parameter :: inflexible = .false.
  logical, parameter :: mandatory = .true.
  logical, parameter :: optional  = .false.
  integer(kind=code_k), parameter :: code_arg_mandatory = 1  ! Argument must appear 1 time
  integer(kind=code_k), parameter :: code_arg_optional  = 2  ! Argument can appear 0 or 1 time
  integer(kind=code_k), parameter :: code_arg_unlimited = 3  ! Argument can appear 0 or more times
                                               ! We could add: Argument can appear 1 or more times
  character(len=*), parameter :: arg_status(3) =  &
    (/ 'mandatory','optional ','unlimited' /)
  !
  ! --- Flag modes -----------------------------------------------------
  integer(kind=code_k), parameter :: keep_none=1
  integer(kind=code_k), parameter :: keep_prod=2
  integer(kind=code_k), parameter :: keep_acti=3
  integer(kind=code_k), parameter :: keep_all =4
  !
  ! --- Parsing utility ------------------------------------------------
  logical, parameter :: verbose = .true.
  logical, parameter :: quiet = .true.
  logical, parameter :: overwrite = .true.
  logical, parameter :: global = .true.
  logical, parameter :: local = .true.
  logical, parameter :: readonly = .true.
  integer(kind=4), parameter :: icomm = 0
  character(len=*), parameter :: strg_star  = '*'  ! smart choice
  character(len=*), parameter :: strg_equal = '='  ! Keep previous value
  integer(kind=code_k), parameter :: code_unresolved = -1
  character(len=*), parameter :: strg_unresolved = "UNRESOLVED"
  !
  ! --- Help utility ---------------------------------------------------
  character(len=*), parameter :: strg_id  = 'idem'
  integer(kind=4), parameter :: stdout=6
  !
  integer(kind=code_k), parameter :: help_format_term =0
  integer(kind=code_k), parameter :: help_format_tex  =1
  integer(kind=code_k), parameter :: help_format_flags=2
  integer(kind=4),  parameter :: help_nformats=2
  character(len=*), parameter :: help_formats(help_nformats) = (/ 'TEX  ','FLAGS' /)
  character(len=*), parameter :: help_extensions(help_nformats) = (/ '.tex','.flg' /)
  !
contains
  !
  function access_status(iaccess)
    !-------------------------------------------------------------------
    ! Translate an access code to string
    !-------------------------------------------------------------------
    character(len=13) :: access_status
    integer(kind=code_k), intent(in) :: iaccess
    !
    select case (iaccess)
    case (code_access_imaset)
      access_status = 'imaset'
    case (code_access_speset)
      access_status = 'speset'
    case (code_access_subset)
      access_status = 'subset'
    case (code_access_blobset)
      access_status = 'blobset'
    case (code_access_fullset)
      access_status = 'fullset'
    case (code_access_imaset_or_speset)
      access_status = 'imaset/speset'
    case (code_access_any)
      access_status = 'anyset'
    case (code_access_user)
      ! Most likely it will be solved as imaset or speset at runtime
      access_status = 'imaset/speset'
    case default
      access_status = '???'
    end select
  end function access_status
  !
  function action_status(iaction)
    !-------------------------------------------------------------------
    ! Translate an action code to string
    !-------------------------------------------------------------------
    character(len=6) :: action_status
    integer(kind=code_k), intent(in) :: iaction
    !
    select case (iaction)
    case (code_read_none)
      action_status = 'none'
    case (code_read_head)
      action_status = 'header'
    case (code_read)
      action_status = 'read'
    case (code_write)
      action_status = 'write'
    case (code_update)
      action_status = 'update'
    case default
      action_status = '???'
    end select
  end function action_status
  !
  function cube_dev_mode()
    use gkernel_interfaces
    !-------------------------------------------------------------------
    ! Return .true. if CUBE is dev mode. Dynamic check as this is not a
    ! compilation-time constant.
    !-------------------------------------------------------------------
    logical :: cube_dev_mode
    character(len=12) :: status
    !
    call sic_getenv('GAG_CUBE_DEV',status)
    cube_dev_mode = status.eq."YES" .or. status.eq."yes"
    !
    ! Could also check for a command-line option or a user variable?
  end function cube_dev_mode
end module cubetools_parameters
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
