!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module mrtindex_types
  use gkernel_types
  use classic_api
  use mrtindex_parameters
  use mrtindex_sec_pointing
  !
  ! Here: only elements on which we will makes searches
  integer(kind=4), parameter :: mrtindex_indx_length=51
  ! Index version:
  ! * 1 never => can not be 1 in Classic V2 files
  ! * 2 on 09-JAN-2017 (going officially online @ Pico)
  ! * 3 on 01-OCT-2024 (introduce solstatus at position 39)
  ! 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=3
  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
    integer(kind=4)   :: solstatus              !    39: [code] Solve status
    integer(kind=4)   :: pad                    !               Memory padding
    character(len=fitsname_length) :: filename  ! 40-49: [char] File name (no directory)
    integer(kind=8)   :: itime                  ! 50-51: [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
    integer(kind=4)                :: solstatus    ! [    code] Solve 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=5
  integer(kind=8), parameter :: sec_tuning_len=0
  ! TO BE DONE
  !
  ! Header
  integer(kind=4), parameter :: mrtcal_maxsec=4  ! 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                   !
    type(sec_pointing_t)  :: poi                   !
  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
    integer(kind=4),                pointer :: solstatus(:)   =>null()  ! Solve 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=16)  :: cfron(mrtcal_indx_mfrontend)  ! Desired frontend(s), 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
    !
    logical            :: lsolv  ! Selection by solve status enabled?
    integer(kind=4)    :: isolv(nsolstatus)  ! Desired solve status(es), if relevant
  end type mrtindex_find_t
end module mrtindex_types
!
module mrtindex_array_types
  use mrtindex_parameters
  use mrtindex_sec_pointing
  !---------------------------------------------------------------------
  ! This module provide array-ified headers, which can be used to load
  ! a collection of headers in memory. Typically needed by command
  ! VARIABLE /INDEX
  !---------------------------------------------------------------------

  type mrtindex_key_arr_t
    integer(kind=4),                allocatable :: version(:)
    integer(kind=4),                allocatable :: telescope(:)
    character(len=8),               allocatable :: projid(:)
    character(len=12),              allocatable :: source(:)
    integer(kind=4),                allocatable :: dobs(:)
    real(kind=8),                   allocatable :: ut(:)
    real(kind=8),                   allocatable :: lst(:)
    real(kind=4),                   allocatable :: az(:)
    real(kind=4),                   allocatable :: el(:)
    real(kind=8),                   allocatable :: lon(:)
    real(kind=8),                   allocatable :: lat(:)
    integer(kind=4),                allocatable :: system(:)
    real(kind=4),                   allocatable :: equinox(:)
    character(len=8),               allocatable :: frontend(:,:)
    integer(kind=4),                allocatable :: scan(:)
    integer(kind=4),                allocatable :: backend(:)
    integer(kind=4),                allocatable :: obstype(:)
    integer(kind=4),                allocatable :: switchmode(:)
    integer(kind=4),                allocatable :: polstatus(:)
    integer(kind=4),                allocatable :: filstatus(:)
    integer(kind=4),                allocatable :: calstatus(:)
    integer(kind=4),                allocatable :: solstatus(:)
    character(len=fitsname_length), allocatable :: filename(:)
  end type mrtindex_key_arr_t

  ! Header (array)
  type mrtindex_header_arr_t
    type(mrtindex_key_arr_t)   :: key
    type(sec_pointing_array_t) :: poi
  end type mrtindex_header_arr_t

  ! Support variable for command "VARIABLE /INDEX"
  type(mrtindex_header_arr_t), save :: mdxhead

end module mrtindex_array_types
!
module mrtindex_parse_types
  use gildas_def
  use gkernel_types
  use mrtindex_parameters
  !
  character(len=*), parameter :: user_find_allfront='* *&*'  ! Find all single-band and all dual-band
  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=128)  :: cfron = user_find_allfront  ! Frontend (receiver) name (or list)
     character(len=completeness_length) :: ccomp = '*'  ! File completeness
     character(len=128)                 :: ccali = '*'  ! Calibration status (or list)
     character(len=128)                 :: csolv = '*'  ! Solve 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
