!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module mrtindex_parameters
  !---------------------------------------------------------------------
  !  Tables of translation between IMB-FITS fields and codes used in
  ! Mrtcal index files
  !  + few other parameters
  !---------------------------------------------------------------------
  !
  integer(kind=4), parameter :: fitsname_length=40  ! Warning: used in data format
  !
  ! Known telescopes
  integer(kind=4), parameter :: telescope_length=12
  integer(kind=4), parameter :: ntelescopes=1
  ! Ad vitam aeternam codes:
  integer(kind=4), parameter :: telescope_unknown=0
  integer(kind=4), parameter :: telescope_iram30m=1
  ! Order must match telescope codes:
  character(len=telescope_length), parameter :: telescopes(0:ntelescopes) =  &
    (/ 'unknown     ','IRAM 30m    ' /)
  !
  ! Known backends
  integer(kind=4), parameter :: backname_length=9
  integer(kind=4), parameter :: nbackends_imbfits=10
  integer(kind=4), parameter :: nbackends_mrtcal=9
  ! Ad vitam aeternam codes:
  integer(kind=4), parameter :: backend_unknown  =0
  integer(kind=4), parameter :: backend_nbc      =1
  integer(kind=4), parameter :: backend_bbc      =2
  integer(kind=4), parameter :: backend_4mhz     =3
  integer(kind=4), parameter :: backend_vespa    =4
  integer(kind=4), parameter :: backend_wilma    =5
  integer(kind=4), parameter :: backend_fts      =6
  integer(kind=4), parameter :: backend_nika1mm  =7
  integer(kind=4), parameter :: backend_nika2mm  =8
  integer(kind=4), parameter :: backend_holo     =9
  ! Used by IMBFITS, do not use for MRTCAL (this code can be modified)
  integer(kind=4), parameter :: backend_continuum=10
  ! Order must match backend codes:
  ! 1) As found in IMBFITS files
  character(len=backname_length), parameter :: backends_imbfits(nbackends_imbfits) =  &
    (/             'NBC      ','BBC      ','4MHZ     ','VESPA    ',  &
       'WILMA    ','FTS      ','NIKA1MM  ','NIKA2MM  ','HOLO     ',  &
       'CONTINUUM'/)
  ! 2) As displayed by MRTCAL
  character(len=backname_length), parameter :: backends_mrtcal(0:nbackends_mrtcal) =  &
    (/ 'UNKNOWN  ','NBC      ','BBC      ','4MHZ     ','VESPA    ',  &
       'WILMA    ','FTS      ','NIKA1MM  ','NIKA2MM  ','HOLO     ' /)
  !
  ! Known observation types
  integer(kind=4), parameter :: obstype_length=11
  integer(kind=4), parameter :: nobstypes_imbfits=9
  integer(kind=4), parameter :: nobstypes_mrtcal =8
  ! Ad vitam aeternam codes:
  integer(kind=4), parameter :: obstype_unknown  =0
  integer(kind=4), parameter :: obstype_pointing =1
  integer(kind=4), parameter :: obstype_focus    =2
  integer(kind=4), parameter :: obstype_calibrate=3
  integer(kind=4), parameter :: obstype_tracked  =4
  integer(kind=4), parameter :: obstype_otf      =5
  integer(kind=4), parameter :: obstype_diy      =6
  integer(kind=4), parameter :: obstype_lissajous=7
  integer(kind=4), parameter :: obstype_tip      =8
  ! Used by IMBFITS, do not use for MRTCAL (this code can be modified)
  integer(kind=4), parameter :: obstype_onoff    =9
  ! Order must match obstype codes:
  ! 1) As found in IMBFITS files
  character(len=obstype_length), parameter :: obstypes_imbfits(0:nobstypes_imbfits) =  &
    (/ 'UNKNOWN    ','POINTING   ','FOCUS      ','CALIBRATE  ',  &
       'TRACK      ','ONTHEFLYMAP','DIY        ','LISSAJOUS  ',  &
       'TIP        ','ONOFF      ' /)
  ! 2) As displayed by MRTCAL
  character(len=obstype_length), parameter :: obstypes_mrtcal(0:nobstypes_mrtcal) =  &
    (/ 'UNKNOWN    ','POINTING   ','FOCUS      ','CALIBRATE  ',  &
       'TRACKED    ','ONTHEFLYMAP','DIY        ','LISSAJOUS  ',  &
       'TIP        ' /)
  !
  ! Known switching mode
  integer(kind=4), parameter :: switchmode_length=18
  integer(kind=4), parameter :: nswitchmodes=4
  ! Ad vitam aeternam codes:
  integer(kind=4), parameter :: switchmode_unk=0
  integer(kind=4), parameter :: switchmode_pos=1
  integer(kind=4), parameter :: switchmode_wob=2
  integer(kind=4), parameter :: switchmode_fre=3
  integer(kind=4), parameter :: switchmode_bea=4
  ! Order must match switchmode codes:
  ! 1) As found in IMBFITS files
  character(len=switchmode_length), parameter :: switchmodes_imbfits(nswitchmodes) =  &
    (/                      'TOTALPOWER        ','WOBBLERSWITCHING  ',  &
       'FREQUENCYSWITCHING','BEAMSWITCHING     ' /)
  ! 2) As displayed by MRTCAL
  character(len=3), parameter :: switchmodes_mrtcal(0:nswitchmodes) =  &
    (/ 'UNK','PSW','WSW','FSW','BSW' /)
  character(len=switchmode_length), parameter :: switchmodes_voxml(0:nswitchmodes) =  &
    (/ 'unknownSwitching  ','totalPower        ','wobblerSwitching  ',  &
       'frequencySwitching','beamSwitching     ' /)
  !
  ! Known polarimetry statuses
  integer(kind=4), parameter :: polstatus_length=3
  integer(kind=4), parameter :: npolstatus=2
  ! Ad vitam aeternam codes:
  integer(kind=4), parameter :: polstatus_no =0
  integer(kind=4), parameter :: polstatus_yes=1
  ! Order must match calibration status codes:
  character(len=polstatus_length), parameter ::  &
    polstatus(0:npolstatus-1) = (/ 'NO ','YES' /)
  !
  ! Known file completeness
  integer(kind=4), parameter :: completeness_length=10
  integer(kind=4), parameter :: ncompleteness=4
  ! Ad vitam aeternam codes:
  integer(kind=4), parameter :: complete_unreadable=1  ! Nothing usable
  integer(kind=4), parameter :: complete_empty     =2  ! 0 subscans
  integer(kind=4), parameter :: complete_partial   =3  ! A few subscans
  integer(kind=4), parameter :: complete_full      =4  ! All the subscans
  ! Order must match completeness codes:
  character(len=completeness_length), parameter :: completenesses(ncompleteness) =   &
    (/ 'UNREADABLE','EMPTY     ','INCOMPLETE','COMPLETE  ' /)
  !
  ! Known calibration statuses
  integer(kind=4), parameter :: calstatus_length=7
  integer(kind=4), parameter :: ncalstatus=5
  ! Ad vitam aeternam codes:
  integer(kind=4), parameter :: calstatus_none   =1
  integer(kind=4), parameter :: calstatus_done   =2
  integer(kind=4), parameter :: calstatus_failed =3
  integer(kind=4), parameter :: calstatus_empty  =4
  integer(kind=4), parameter :: calstatus_skipped=5
  ! Order must match calibration status codes:
  character(len=calstatus_length), parameter ::  &
    calstatus(ncalstatus) = (/ 'NONE   ','DONE   ','FAILED ','EMPTY  ','SKIPPED' /)
  !
end module mrtindex_parameters
!
module mrtindex_types
  use gkernel_types
  use classic_api
  use mrtindex_parameters
  !
  ! Here: only elements on which we will makes searches
  integer(kind=4), parameter :: mrtindex_indx_length=50
  ! Index version:
  ! * 1 never => can not be 1 in Classic V2 files
  ! * 2 on 09-JAN-2017 (going officially online @ Pico)
  ! Note that numbers 2 to 11 were used during the development phase of
  ! Mrtcal (2013 to 2016); in particular 11 was used during all year 2016.
  integer(kind=4), parameter :: mrtcal_indx_version=2
  integer(kind=4), parameter :: mrtcal_indx_mfrontend=4  ! Warning: used in data format
  type mrtindex_indx_t
    sequence
    integer(kind=8)   :: bloc                   !  1- 2: [record] Entry address
    integer(kind=4)   :: word                   !     3: [word] Position in this record
    integer(kind=4)   :: version                !     4: [---] Entry version
    integer(kind=4)   :: telescope              !     5: [code] Telescope
    character(len=12) :: source                 !  6- 8: [---] Source name
    character(len=8)  :: projid                 !  9-10: [---] Project Id
    real(kind=8)      :: ut                     ! 11-12: [rad] Observation time
    real(kind=8)      :: lst                    ! 13-14: [sec] Local Sidereal Time
    real(kind=4)      :: az                     !    15: [rad] Azimuth
    real(kind=4)      :: el                     !    16: [rad] Elevation
    real(kind=8)      :: lon                    ! 17-18: [rad] Longitude
    real(kind=8)      :: lat                    ! 19-20: [rad] Latitude
    integer(kind=4)   :: system                 !    21: [code] System of coordinates for lon-lat
    real(kind=4)      :: equinox                !    22: [year] Equinox if system is equatorial
    character(len=8)  :: frontend(mrtcal_indx_mfrontend)  ! 23-30: [char] Receiver name(s)
    integer(kind=4)   :: dobs                   !    31: [gag_date] Observation date
    integer(kind=4)   :: scan                   !    32: [---] Scan number
    integer(kind=4)   :: backend                !    33: [code] Backend
    integer(kind=4)   :: obstype                !    34: [code] Observation type
    integer(kind=4)   :: switchmode             !    35: [code] Switching mode
    integer(kind=4)   :: polstatus              !    36: [0|1] Polarimetry?
    integer(kind=4)   :: filstatus              !    37: Can read file or not?
    integer(kind=4)   :: calstatus              !    38: [code] Calibration status
    character(len=fitsname_length) :: filename  ! 39-48: [char] File name (no directory)
    integer(kind=8)   :: itime                  ! 49-50: [usec] Last indexing time
  end type mrtindex_indx_t
  !
  ! "Section key" (copy of index, always present)
  integer(kind=4), parameter :: sec_key_id=0  ! Not a real section in file
  type mrtindex_key_t
    integer(kind=4)                :: version      ! [     ---] Entry version
    integer(kind=4)                :: telescope    ! [    code] Telescope
    character(len=8)               :: projid       ! [     ---] Project Id
    character(len=12)              :: source       ! [     ---] Source name
    integer(kind=4)                :: dobs         ! [gag_date] Observation date
    real(kind=8)                   :: ut           ! [     rad] Observation time
    real(kind=8)                   :: lst          ! [     sec] Local Sideral Time
    real(kind=4)                   :: az           ! [     rad] Azimuth
    real(kind=4)                   :: el           ! [     rad] Elevation
    real(kind=8)                   :: lon          ! [     rad] Longitude
    real(kind=8)                   :: lat          ! [     rad] Latitude
    integer(kind=4)                :: system       ! [    code] System of coordinates for lon-lat
    real(kind=4)                   :: equinox      ! [    year] Equinox if system is equatorial
    character(len=8)  :: frontend(mrtcal_indx_mfrontend)  ! [char] Receiver name(s)
    integer(kind=4)                :: scan         ! [     ---] Scan number
    integer(kind=4)                :: backend      ! [    code] Backend
    integer(kind=4)                :: obstype      ! [    code] Observation type
    integer(kind=4)                :: switchmode   ! [    code] Switching mode
    integer(kind=4)                :: polstatus    ! [     0|1] Polarimetry?
    integer(kind=4)                :: filstatus    ! [    code] Can read file or not?
    integer(kind=4)                :: calstatus    ! [    code] Calibration status
    character(len=fitsname_length) :: filename     ! [  string] File name (no directory)
  end type mrtindex_key_t
  !
  ! Section "primary" (IMBFITS primary header)
  integer(kind=4), parameter :: sec_prim_id=1
  integer(kind=8), parameter :: sec_prim_len=1_8
  type sec_primary_t
     real(kind=4)      :: imbfvers ! 1 [---] IMBFITS version
   ! real(kind=8)      :: timegoal !   [sec] Integration time declared
   ! integer(kind=4)   :: nsubgoal !   [---] Number of subscans declared
   ! integer(kind=4)   :: nsub     !   [---] Number of subscans present
  end type sec_primary_t
  !
  ! Section Calibration: reserved for calibration scans
  integer(kind=4), parameter :: sec_calib_id=2
! integer(kind=8), parameter :: sec_calib_len=unlimited (dynamic read/write)
  type sec_calib_t
    ! Save the calibration arrays for the calibration scan
    ! ZZZ Need a better definition
    integer(kind=4)               :: nfreq        ! [-----] Number of frequencies
    integer(kind=4)               :: nset         ! [-----] Number of setups
    integer(kind=4)               :: npix         ! [-----] Number of pixels
    character(len=8), allocatable :: frontend(:)  ! [-----] Receiver names[Nset]
    real(kind=8),     allocatable :: freq(:,:,:)  ! [MHz  ] Frequencies[Nfreq,Nset,Npix]
    real(kind=4),     allocatable :: atsys(:,:,:) ! [K    ] Attenuated Tsys[Nfreq,Nset,Npix]
    real(kind=4),     allocatable :: ztau(:,:,:)  ! [neper] Zenith tau[Nfreq,Nset,Npix]
  end type sec_calib_t
  !
  ! Section Science: reserved for science scans.
  integer(kind=4), parameter :: sec_science_id=3
  integer(kind=8), parameter :: sec_science_len=4
  type sec_science_t
    ! Save the reference(s) of the calibration scan(s) used:
    integer(kind=4) :: caldobs  ! [gag_date]  Date of the associated calibr. scan
    integer(kind=4) :: calscan  ! [        ]  Scan
    integer(kind=4) :: calback  ! [    code]  Backend
    integer(kind=4) :: calvers  ! [        ]  Version
  end type sec_science_t
  !
  ! Section Tuning: for both calibration and science scans. Save the
  ! relevant tunings which were used for calibration.
  integer(kind=4), parameter :: sec_tuning_id=4
  integer(kind=8), parameter :: sec_tuning_len=0
  ! TO BE DONE
  !
  ! Header
  integer(kind=4), parameter :: mrtcal_maxsec=3  ! Maximum number of known sections
  type mrtindex_header_t
    logical               :: presec(mrtcal_maxsec) ! Which section are presents
    type(mrtindex_key_t)    :: key                   ! ~ duplicate of index
    type(sec_primary_t)   :: pri                   !
    type(sec_calib_t)     :: cal                   !
    type(sec_science_t)   :: sci                   !
  end type mrtindex_header_t
  !
  type mrtindex_entry_t
    type(mrtindex_indx_t)       :: indx  ! The entry indx
    type(classic_entrydesc_t) :: desc  ! The entry descriptor
    type(mrtindex_header_t)     :: head  ! The entry header
  end type mrtindex_entry_t
  !
  type mrtindex_optimize_t
    integer(kind=entry_length) :: next=1  ! Number of observations in index + 1
    integer(kind=8),                pointer :: bloc(:)        =>null()  ! Bloc numbers
    integer(kind=4),                pointer :: word(:)        =>null()  ! Position in record
    integer(kind=4),                pointer :: version(:)     =>null()  ! Entry version
    integer(kind=4),                pointer :: telescope(:)   =>null()  ! Telescope code
    character(len=8),               pointer :: projid(:)      =>null()  ! Project Id
    character(len=12),              pointer :: source(:)      =>null()  ! Source name
    integer(kind=4),                pointer :: dobs(:)        =>null()  ! Observation date
    real(kind=8),                   pointer :: ut(:)          =>null()  ! Observation time
    real(kind=8),                   pointer :: lst(:)         =>null()  ! Local Sidereal time
    real(kind=4),                   pointer :: az(:)          =>null()  ! Azimuth
    real(kind=4),                   pointer :: el(:)          =>null()  ! Elevation
    real(kind=8),                   pointer :: lon(:)         =>null()  ! Longitude
    real(kind=8),                   pointer :: lat(:)         =>null()  ! Latitude
    integer(kind=4),                pointer :: system(:)      =>null()  ! System of coordinates for lon-lat
    real(kind=4),                   pointer :: equinox(:)     =>null()  ! Equinox if system is equatorial
    character(len=8),               pointer :: frontend(:,:)  =>null()  ! Receiver name(s)
    integer(kind=4),                pointer :: scan(:)        =>null()  ! Scan number
    integer(kind=4),                pointer :: backend(:)     =>null()  ! Backend code
    integer(kind=4),                pointer :: obstype(:)     =>null()  ! Obstype code
    integer(kind=4),                pointer :: switchmode(:)  =>null()  ! Switching mode
    integer(kind=4),                pointer :: polstatus(:)   =>null()  ! Polarimetry
    integer(kind=4),                pointer :: filstatus(:)   =>null()  ! File completeness
    integer(kind=4),                pointer :: calstatus(:)   =>null()  ! Calibration status
    character(len=fitsname_length), pointer :: filename(:)    =>null()  ! File name (no directory)
    integer(kind=8),                pointer :: itime(:)       =>null()  ! Last indexing time
    ! Not in data
    integer(kind=entry_length),     pointer :: num(:)         =>null()  ! "Observation" number
    integer(kind=entry_length),     pointer :: mnum(:)        =>null()  ! Entry number in IX (memory)
    integer(kind=entry_length),     pointer :: fnum(:)        =>null()  ! Entry number in file
    integer(kind=entry_length),     pointer :: sort(:)        =>null()  ! Sorting list
    integer(kind=4),                pointer :: idir(:)        =>null()  ! Host directory identifier
    logical,                        pointer :: islast(:)      =>null()  ! Is this the obs. last version?
  end type mrtindex_optimize_t
  !
  type :: mrtindex_find_t
    logical            :: llast  ! Selection of last version only enabled?
    !
    logical            :: ldate  ! Selection by date enabled?
    type(sic_listi4_t) :: idate  ! Desired scan list(s), if relevant
    !
    logical            :: lscan  ! Selection by iscan enabled?
    type(sic_listi4_t) :: iscan  ! Desired scan list(s), if relevant
    !
    logical            :: lback  ! Selection by backend enabled?
    integer(kind=4)    :: iback(nbackends_mrtcal)  ! Desired backend code(s), if relevant
    !
    logical            :: lobst  ! Selection by observation type enabled?
    integer(kind=4)    :: iobst(nobstypes_mrtcal)  ! Desired obstype code(s), if relevant
    !
    logical            :: lswit  ! Selection by switching mode enabled?
    integer(kind=4)    :: iswit(nswitchmodes)  ! Desired switchmode code(s), if relevant
    !
    logical            :: lpola  ! Selection by cpola enabled?
    integer(kind=4)    :: ipola  ! Desired polarimetry status, if relevant
    !
    logical            :: lsour  ! Selection by csour enabled?
    character(len=12)  :: csour  ! Desired source name, if relevant
    !
    logical            :: lproj  ! Selection by cproj enabled?
    character(len=8)   :: cproj  ! Desired project id, if relevant
    !
    logical            :: lfron  ! Selection by cfron enabled?
    character(len=8)   :: cfron  ! Desired frontend, if relevant
    !
    logical            :: lcomp  ! Selection by file completeness enabled?
    integer(kind=4)    :: icomp  ! Desired readability, if relevant
    !
    logical            :: lcali  ! Selection by calibration status enabled?
    integer(kind=4)    :: icali(ncalstatus)  ! Desired calibration status(es), if relevant
  end type mrtindex_find_t
  !
end module mrtindex_types
!
module mrtindex_parse_types
  use gildas_def
  use gkernel_types
  use mrtindex_parameters
  !
  type user_calib_t
     ! Type used for parsing CALIBRATE or FIND options. Get arguments
     ! as character strings (because '*' is often accepted), interpret
     ! them elsewhere
     character(len=128)                 :: cscan = '*'  ! Scan number (or list)
     character(len=128)                 :: cback = '*'  ! Backend string (or list)
     character(len=128)                 :: cdate = '*'  ! Date string (or list)
     character(len=128)                 :: cobst = '*'  ! Obstype (or list)
     character(len=128)                 :: cswit = '*'  ! Switchmode (or list)
     character(len=8)                   :: cpola = '*'  ! Polarimetry
     character(len=12)                  :: csour = '*'  ! Source name
     character(len=8)                   :: cproj = '*'  ! Project name
     character(len=8)                   :: cfron = '*'  ! Frontend (receiver) name
     character(len=completeness_length) :: ccomp = '*'  ! File completeness
     character(len=128)                 :: ccali = '*'  ! Calibration status (or list)
  end type user_calib_t
  !
  type user_find_t
     ! Support for LAS\FIND hook on Mrtcal User Section. Selection criteria
     logical :: ltypes(0:nobstypes_mrtcal)  ! Obs. Types selected
  end type user_find_t
  !
  integer(kind=4), parameter :: imbfits_pattern_length=64
  type user_pattern_t
     ! Support for INDEX /PATTERN or /DATE
     logical :: bylist
     character(len=imbfits_pattern_length) :: custom    ! By user custom pattern
     type(sic_listi4_t)                    :: datelist  ! By list of dates
  end type user_pattern_t
  !
  type backend_list_t
     integer(kind=4) :: n = 0 ! Number of backends available in current scan
     integer(kind=4),                pointer :: backcode(:) => null() ! Backend code
     character(len=filename_length), pointer :: file(:)     => null() ! Associated file name
  end type backend_list_t
end module mrtindex_parse_types
!
module mrtindex_vars
  use gildas_def
  use classic_api
  use mrtindex_types
  use mrtindex_parse_types
  !
  ! ZZZ One set of buffers per file?
  type(classic_recordbuf_t) :: obufbi
  type(classic_recordbuf_t) :: obufobs
  type(classic_recordbuf_t) :: ibufbi
  type(classic_recordbuf_t) :: ibufobs
  !
  ! IX index files
  integer(kind=4) :: ix_ndir    ! Current number of index files loaded in IX
  integer(kind=4) :: ix_opened  ! Identifier of the one which is currently Fortran-opened
  character(len=filename_length), allocatable :: ix_dirs(:)   ! Directories
  type(classic_file_t),           allocatable :: ix_files(:)  ! Index files
  integer(kind=4) :: ox_fileid=0  ! Output index file (identifier)
  !
  ! Pre-reserved logical units for index files
  integer(kind=4) :: ix_lun,ox_lun
  !
end module mrtindex_vars
!
module mrtindex_messaging
  use gbl_message
  !
  type :: mrtindex_debug_message_t
    integer(kind=4) :: alloc   ! Support for MSET DEBUG INDEX ALLOCATION
    integer(kind=4) :: others  ! Support for MSET DEBUG INDEX OTHERS
  end type mrtindex_debug_message_t
  !
  ! Set the default at startup:
  !  iseve%alloc = seve%d
  !  iseve%others = seve%d
  type(mrtindex_debug_message_t) :: iseve = mrtindex_debug_message_t(seve%d,seve%d)
  !
end module mrtindex_messaging
