module classic_interfaces_private
  interface
    subroutine classic_message(mkind,procname,message)
      !---------------------------------------------------------------------
      ! @ private
      ! Messaging facility for the current library. Calls the low-level
      ! (internal) messaging routine with its own identifier.
      !---------------------------------------------------------------------
      integer(kind=4),  intent(in) :: mkind     ! Message kind
      character(len=*), intent(in) :: procname  ! Name of calling procedure
      character(len=*), intent(in) :: message   ! Message string
    end subroutine classic_message
  end interface
  !
  interface
    subroutine classic_iostat(mkind,procname,ier)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ private
      ! Output system message corresponding to IO error code IER, and
      ! using the MESSAGE routine
      !---------------------------------------------------------------------
      integer,          intent(in) :: mkind     ! Message severity
      character(len=*), intent(in) :: procname  ! Calling routine name
      integer,          intent(in) :: ier       ! IO error number
    end subroutine classic_iostat
  end interface
  !
  interface
    subroutine classic_code
      use classic_vars
      !---------------------------------------------------------------------
      ! @ private
      !   Set the identification codes for the current system.
      !---------------------------------------------------------------------
    end subroutine classic_code
  end interface
  !
  interface
    subroutine classic_convcod(filecode,lversion,lsingle,lpdp11,convcode,error)
      use gbl_convert
      use gbl_message
      use classic_vars
      !---------------------------------------------------------------------
      ! @ private
      !   Return the conversion code from File Data Type to System Data
      ! Type, and the extra informations which can be deduced from the File
      ! code.
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)    :: filecode  ! File code
      integer(kind=4), intent(out)   :: lversion  ! File version
      logical,         intent(out)   :: lsingle   ! Single or multiple?
      logical,         intent(out)   :: lpdp11    ! Old PDP 11 system?
      integer(kind=4), intent(out)   :: convcode  ! Conversion code
      logical,         intent(inout) :: error     ! Logical error flag
    end subroutine classic_convcod
  end interface
  !
  interface
    subroutine classic_conv(conv,error)
      use gildas_def
      use gbl_convert
      use gbl_message
      use classic_types
      !---------------------------------------------------------------------
      ! @ private
      !  Set up the file conversion routines: read/write file-data-type
      ! to/from the system-data-type conversion routines.
      !---------------------------------------------------------------------
      type(classic_fileconv_t), intent(inout) :: conv   !
      logical,                  intent(inout) :: error  ! Logical error flag
    end subroutine classic_conv
  end interface
  !
  interface
    subroutine entrydesc_init_v1(ed,xnum,maxsec,version,error)
      use gbl_message
      use classic_params
      use classic_types
      use classic_vars
      !---------------------------------------------------------------------
      ! @ private
      !   Initialize the Entry Descriptor of a new observation, suited for
      ! a version 1 file
      !---------------------------------------------------------------------
      type(classic_entrydesc_t),  intent(out)   :: ed       ! The new Entry Descriptor
      integer(kind=entry_length), intent(in)    :: xnum     ! The corresponding Entry number
      integer(kind=4),            intent(in)    :: maxsec   ! Maximum number of sections the ed can describe
      integer(kind=4),            intent(in)    :: version  ! Observation version
      logical,                    intent(inout) :: error    ! Logical error flag
    end subroutine entrydesc_init_v1
  end interface
  !
  interface
    subroutine entrydesc_init_v2(ed,xnum,maxsec,version,error)
      use classic_params
      use classic_types
      use classic_vars
      !---------------------------------------------------------------------
      ! @ private
      !   Initialize the Entry Descriptor of a new observation, suited for
      ! a version 2 file
      !---------------------------------------------------------------------
      type(classic_entrydesc_t),  intent(out)   :: ed       ! The new Entry Descriptor
      integer(kind=entry_length), intent(in)    :: xnum     ! The corresponding Entry number
      integer(kind=4),            intent(in)    :: maxsec   ! Maximum number of sections the ed can describe
      integer(kind=4),            intent(in)    :: version  ! Observation version
      logical,                    intent(inout) :: error    ! Logical error flag
    end subroutine entrydesc_init_v2
  end interface
  !
  interface
    subroutine entrydesc_read_v1(file,buf,edv2,error)
      use gbl_message
      use classic_params
      use classic_types
      use classic_vars
      !---------------------------------------------------------------------
      ! @ private
      !   Read the Entry Descriptor, Version 1
      !---------------------------------------------------------------------
      type(classic_file_t),      intent(in)    :: file   !
      type(classic_recordbuf_t), intent(inout) :: buf    ! Working buffer
      type(classic_entrydesc_t), intent(inout) :: edv2   ! The Entry Descriptor read
      logical,                   intent(inout) :: error  ! Logical error flag
    end subroutine entrydesc_read_v1
  end interface
  !
  interface
    subroutine entrydesc_v1tov2(ed1,ed2,error)
      use classic_types
      !---------------------------------------------------------------------
      ! @ private
      ! Convert a Version 1 Entry Descriptor to a Version 2
      !---------------------------------------------------------------------
      type(entrydesc_v1_t),      intent(in)    :: ed1    ! Version 1
      type(classic_entrydesc_t), intent(out)   :: ed2    ! Version 2
      logical,                   intent(inout) :: error  ! Logical error flag
    end subroutine entrydesc_v1tov2
  end interface
  !
  interface
    subroutine entrydesc_read_v2(file,buf,ed,error)
      use gbl_message
      use classic_params
      use classic_types
      use classic_vars
      !---------------------------------------------------------------------
      ! @ private
      !   Read the Entry Descriptor, Version 2
      !---------------------------------------------------------------------
      type(classic_file_t),      intent(in)    :: file   !
      type(classic_recordbuf_t), intent(inout) :: buf    ! Working buffer
      type(classic_entrydesc_t), intent(inout) :: ed     ! The Entry Descriptor read
      logical,                   intent(inout) :: error  ! Logical error flag
    end subroutine entrydesc_read_v2
  end interface
  !
  interface
    subroutine entrydesc_write_v1(file,buf,edv2,error)
      use gbl_message
      use classic_params
      use classic_types
      use classic_vars
      !---------------------------------------------------------------------
      ! @ private
      !   Write the input Entry Descriptor, Version 1
      !---------------------------------------------------------------------
      type(classic_file_t),      intent(in)    :: file   !
      type(classic_recordbuf_t), intent(inout) :: buf    ! Working buffer
      type(classic_entrydesc_t), intent(in)    :: edv2   ! The Entry Descriptor to be written
      logical,                   intent(inout) :: error  ! Logical error flag
    end subroutine entrydesc_write_v1
  end interface
  !
  interface
    subroutine entrydesc_v2tov1(ed2,ed1,error)
      use classic_types
      !---------------------------------------------------------------------
      ! @ private
      ! Convert a Version 2 Entry Descriptor to a Version 1
      !---------------------------------------------------------------------
      type(classic_entrydesc_t), intent(in)    :: ed2    ! Version 2
      type(entrydesc_v1_t),      intent(out)   :: ed1    ! Version 1
      logical,                   intent(inout) :: error  ! Logical error flag
    end subroutine entrydesc_v2tov1
  end interface
  !
  interface
    subroutine entrydesc_write_v2(file,buf,ed,error)
      use gbl_message
      use classic_params
      use classic_types
      use classic_vars
      !---------------------------------------------------------------------
      ! @ private
      !   Write the input Entry Descriptor, Version 2
      !---------------------------------------------------------------------
      type(classic_file_t),      intent(in)    :: file   !
      type(classic_recordbuf_t), intent(inout) :: buf    ! Working buffer
      type(classic_entrydesc_t), intent(in)    :: ed     ! The Entry Descriptor to be written
      logical,                   intent(inout) :: error  ! Logical error flag
    end subroutine entrydesc_write_v2
  end interface
  !
  interface
    subroutine entrydesc_section_add(ed,iden,leng,error)
      use gbl_message
      use classic_params
      use classic_types
      !---------------------------------------------------------------------
      ! @ private
      ! Add a new section in the Entry Descriptor. Assume it does not
      ! exist yet
      !---------------------------------------------------------------------
      type(classic_entrydesc_t), intent(inout) :: ed     ! The Entry Descriptor
      integer(kind=4),           intent(in)    :: iden   ! The section identifier
      integer(kind=data_length), intent(in)    :: leng   ! The section length
      logical,                   intent(inout) :: error  ! Logical error flag
    end subroutine entrydesc_section_add
  end interface
  !
  interface
    subroutine filedesc_init_common(fkind,vind,lind,lsingle,gex,fdesc,error)
      use gbl_message
      use classic_params
      use classic_types
      !---------------------------------------------------------------------
      ! @ private
      !  Initialize the common part of File Descriptor structure in memory
      ! (i.e. V2), suited for any File Version
      !---------------------------------------------------------------------
      integer(kind=4),          intent(in)    :: fkind    ! File kind
      integer(kind=4),          intent(in)    :: vind     ! Index version
      integer(kind=4),          intent(in)    :: lind     ! Index length (words)
      logical,                  intent(in)    :: lsingle  ! Single or multiple?
      real(kind=4),             intent(in)    :: gex      ! Extension growth
      type(classic_filedesc_t), intent(inout) :: fdesc    ! File Descriptor
      logical,                  intent(inout) :: error    !
    end subroutine filedesc_init_common
  end interface
  !
  interface
    subroutine filedesc_init_v1(fdesc,error)
      use gbl_message
      use classic_params
      use classic_types
      use classic_vars
      !---------------------------------------------------------------------
      ! @ private
      !  Initialize the File Descriptor structure in memory (i.e. V2),
      ! suited for Version 1 files
      !---------------------------------------------------------------------
      type(classic_filedesc_t), intent(inout) :: fdesc  ! File Descriptor
      logical,                  intent(inout) :: error  !
    end subroutine filedesc_init_v1
  end interface
  !
  interface
    subroutine filedesc_init_v2(fdesc,error)
      use gbl_message
      use classic_types
      use classic_vars
      !---------------------------------------------------------------------
      ! @ private
      !  Initialize the File Descriptor structure in memory (i.e. V2),
      ! suited for Version 2 files
      !---------------------------------------------------------------------
      type(classic_filedesc_t), intent(inout) :: fdesc  ! File Descriptor
      logical,                  intent(inout) :: error  !
    end subroutine filedesc_init_v2
  end interface
  !
  interface
    subroutine filedesc_init_lex1(lsize,fdesc,error)
      use gbl_message
      use classic_params
      use classic_types
      !---------------------------------------------------------------------
      ! @ private
      !   Compute the extension length. mex, gex and several parameters must
      ! have already been set.
      !---------------------------------------------------------------------
      integer(kind=entry_length), intent(in)    :: lsize  ! Max number of entries in the file
      type(classic_filedesc_t),   intent(inout) :: fdesc  ! File Descriptor
      logical,                    intent(inout) :: error  !
    end subroutine filedesc_init_lex1
  end interface
  !
  interface
    subroutine filedesc_incr(lun,fdesc,full,error)
      use gbl_message
      use classic_types
      use classic_vars
      !---------------------------------------------------------------------
      ! @ private
      ! Increment the File Descriptor, i.e. add 1 new extension
      !---------------------------------------------------------------------
      integer(kind=4),          intent(in)    :: lun    ! File logical unit
      type(classic_filedesc_t), intent(inout) :: fdesc  ! File Descriptor
      logical,                  intent(out)   :: full   ! Is the index full?
      logical,                  intent(inout) :: error  ! Logical error flag
    end subroutine filedesc_incr
  end interface
  !
  interface
    subroutine filedesc_read_v1(file,error)
      use gildas_def
      use gbl_message
      use classic_types
      !---------------------------------------------------------------------
      ! @ private
      !  Read the File Descriptor from the file, version 1 + conversion to
      ! structure in memory, version 2
      !---------------------------------------------------------------------
      type(classic_file_t), intent(inout) :: file   !
      logical,              intent(out)   :: error  ! Logical error flag
    end subroutine filedesc_read_v1
  end interface
  !
  interface
    subroutine filedesc_v1tov2(fdesc1,fdesc2,error)
      use classic_params
      use classic_types
      use classic_vars
      !---------------------------------------------------------------------
      ! @ private
      !---------------------------------------------------------------------
      type(filedesc_v1_t),      intent(in)    :: fdesc1  !
      type(classic_filedesc_t), intent(inout) :: fdesc2  ! INOUT because of allocatable AEX(:)
      logical,                  intent(inout) :: error   !
    end subroutine filedesc_v1tov2
  end interface
  !
  interface
    subroutine filedesc_read_v2(file,error)
      use gildas_def
      use gbl_format
      use gbl_message
      use classic_types
      !---------------------------------------------------------------------
      ! @ private
      !  Read the File Descriptor from the file, version 2
      !---------------------------------------------------------------------
      type(classic_file_t), intent(inout) :: file   !
      logical,              intent(out)   :: error  ! Logical error flag
    end subroutine filedesc_read_v2
  end interface
  !
  interface
    subroutine filedesc_write_v1(file,error)
      use gildas_def
      use gbl_format
      use gbl_message
      use classic_types
      !---------------------------------------------------------------------
      ! @ private
      ! Write the File Descriptor to the file, version 1.
      !---------------------------------------------------------------------
      type(classic_file_t), intent(in)    :: file   !
      logical,              intent(inout) :: error  ! Logical error flag
    end subroutine filedesc_write_v1
  end interface
  !
  interface
    subroutine filedesc_v2tov1(fdesc2,fdesc1,error)
      use gbl_message
      use classic_types
      use classic_vars
      !---------------------------------------------------------------------
      ! @ private
      !---------------------------------------------------------------------
      type(classic_filedesc_t), intent(in)    :: fdesc2  !
      type(filedesc_v1_t),      intent(out)   :: fdesc1  !
      logical,                  intent(inout) :: error   !
    end subroutine filedesc_v2tov1
  end interface
  !
  interface
    subroutine filedesc_write_v2(file,error)
      use gildas_def
      use gbl_format
      use gbl_message
      use classic_types
      !---------------------------------------------------------------------
      ! @ private
      ! Write the File Descriptor to the file, version 2.
      !---------------------------------------------------------------------
      type(classic_file_t), intent(in)    :: file   !
      logical,              intent(inout) :: error  ! Logical error flag
    end subroutine filedesc_write_v2
  end interface
  !
  interface
    subroutine filedesc_update(buf,nword,fdesc,error)
      use classic_params
      use classic_types
      !---------------------------------------------------------------------
      ! @ private
      !  Update the file descriptor (nextrec, nextword) after a buffer has
      ! been written.
      !---------------------------------------------------------------------
      type(classic_recordbuf_t), intent(in)    :: buf    !
      integer(kind=data_length), intent(in)    :: nword  !
      type(classic_filedesc_t),  intent(inout) :: fdesc  !
      logical,                   intent(inout) :: error  ! Logical error flag
    end subroutine filedesc_update
  end interface
  !
  interface
    subroutine reallocate_aex(fdesc,len,error)
      use gbl_message
      use classic_types
      !---------------------------------------------------------------------
      ! @ private
      !  (Re)allocate the fdesc%aex(:) and fdesc%lexn(:) arrays
      !---------------------------------------------------------------------
      type(classic_filedesc_t), intent(inout) :: fdesc  !
      integer(kind=4),          intent(in)    :: len    ! New length required
      logical,                  intent(inout) :: error  !
    end subroutine reallocate_aex
  end interface
  !
  interface
    subroutine deallocate_aex(fdesc,error)
      use gbl_message
      use classic_types
      !---------------------------------------------------------------------
      ! @ private
      !  Deallocate (if needed) the fdesc%aex(:) and fdesc%lexn(:) arrays
      !---------------------------------------------------------------------
      type(classic_filedesc_t), intent(inout) :: fdesc  !
      logical,                  intent(inout) :: error  !
    end subroutine deallocate_aex
  end interface
  !
  interface
    subroutine classic_file_loss_v1(file,unused,error)
      use gbl_message
      use gkernel_types
      use classic_params
      use classic_types
      !---------------------------------------------------------------------
      ! @ private
      ! Parse the input file and search for unused (lost) bytes
      !---------------------------------------------------------------------
      type(classic_file_t), intent(inout) :: file    !
      integer(kind=4),      intent(in)    :: unused  ! Number of unused bytes per Index
      logical,              intent(inout) :: error   !
    end subroutine classic_file_loss_v1
  end interface
  !
  interface
    subroutine classic_file_loss_v2(file,unused,error)
      use gbl_message
      use gkernel_types
      use classic_params
      use classic_types
      !---------------------------------------------------------------------
      ! @ private
      ! Parse the input file and search for unused (lost) bytes
      !---------------------------------------------------------------------
      type(classic_file_t), intent(inout) :: file    !
      integer(kind=4),      intent(in)    :: unused  ! Number of unused bytes per Index
      logical,              intent(inout) :: error   !
    end subroutine classic_file_loss_v2
  end interface
  !
  interface
    subroutine classic_file_loss_index(fdesc,unused,nlost,ntot)
      use gbl_message
      use classic_params
      use classic_types
      !---------------------------------------------------------------------
      ! @ private
      !  Compute the bytes lost in the File Index. This is a function of
      ! the Index growth, not of the File Version.
      !---------------------------------------------------------------------
      type(classic_filedesc_t), intent(in)    :: fdesc   ! The File Descriptor
      integer(kind=4),          intent(in)    :: unused  ! Number of unused bytes per Index
      integer(kind=8),          intent(out)   :: nlost   ! Number of bytes lost
      integer(kind=8),          intent(out)   :: ntot    ! Total number of bytes
    end subroutine classic_file_loss_index
  end interface
  !
  interface
    subroutine entryindex_new(file,entry_num,full,error)
      use gbl_message
      use classic_params
      use classic_types
      !---------------------------------------------------------------------
      ! @ private
      !   Allocate room (i.e. a new extension index), if needed, for the
      ! entry 'entry_num'.
      !---------------------------------------------------------------------
      type(classic_file_t),       intent(inout) :: file       !
      integer(kind=entry_length), intent(in)    :: entry_num  ! Entry number
      logical,                    intent(out)   :: full       ! Index is full?
      logical,                    intent(inout) :: error      ! Logical errror flag
    end subroutine entryindex_new
  end interface
  !
  interface
    subroutine entryindex_readrec(file,entry_num,buf,error)
      use gildas_def
      use gbl_message
      use classic_params
      use classic_types
      !---------------------------------------------------------------------
      ! @ private
      !   Read the record where the entry index 'entry_num' starts. Return
      ! this record in the given buffer. This subroutine has 2 goals:
      !  - from 'entry_num' find in which extension the entry is, and in
      !    which record its index is found,
      !  - set up the 'buffer' type correctly i.e. description and buffer.
      !---------------------------------------------------------------------
      type(classic_file_t),       intent(in)    :: file       !
      integer(kind=entry_length), intent(in)    :: entry_num  !
      type(classic_recordbuf_t),  intent(inout) :: buf        !
      logical,                    intent(inout) :: error      !
    end subroutine entryindex_readrec
  end interface
  !
  interface
    subroutine indexaddr_frombuf_v1(data,ind,conv,error)
      use gildas_def
      use classic_types
      !---------------------------------------------------------------------
      ! @ private
      !  Read the Index previously loaded in buf%data, position k
      !  This routine is generic and do not know the details about the
      ! Index, so it reads only the first element: in File Version 1 it
      ! must be the Entry Address coded as an Integer*4 (returned in addr8)
      !---------------------------------------------------------------------
      integer(kind=4),          intent(in)    :: data(*)  !
      type(indx_basic_v2_t),    intent(out)   :: ind      !
      type(classic_fileconv_t), intent(in)    :: conv     !
      logical,                  intent(inout) :: error    !
    end subroutine indexaddr_frombuf_v1
  end interface
  !
  interface
    subroutine indexaddr_frombuf_v2(data,ind,conv,error)
      use gildas_def
      use classic_types
      !---------------------------------------------------------------------
      ! @ private
      !  Read the Index previously loaded in buf%data, position k
      !  This routine is generic and do not know the details about the
      ! Index, so it reads only the 2 first elements: in File Version 2 it
      ! must be the Entry Address (record and word)
      !---------------------------------------------------------------------
      integer(kind=4),          intent(in)    :: data(*)  !
      type(indx_basic_v2_t),    intent(out)   :: ind      !
      type(classic_fileconv_t), intent(in)    :: conv     !
      logical,                  intent(inout) :: error    !
    end subroutine indexaddr_frombuf_v2
  end interface
  !
  interface
    subroutine recordbuf_close(buf,error)
      use gbl_message
      use classic_types
      !----------------------------------------------------------------------
      ! @ private
      !   Flush the currently opened record to the appropriate record in the
      ! output file
      !----------------------------------------------------------------------
      type(classic_recordbuf_t), intent(in)    :: buf    ! Working buffer
      logical,                   intent(inout) :: error  ! Logical error flag
    end subroutine recordbuf_close
  end interface
  !
  interface
    subroutine toc_select_one(rname,toc,keywords,key,p_format,error)
      use toc_types
      !---------------------------------------------------------------------
      ! @ private
      !  Compute the equivalence classes for one keyword
      !---------------------------------------------------------------------
      character(len=*),       intent(in)            :: rname        ! Calling routine name
      type(toc_t),            intent(inout), target :: toc          !
      character(len=*),       intent(in)            :: keywords(1)  !
      type(toc_descriptor_t), pointer               :: key          ! Associated on return
      interface
        subroutine p_format(key,ival,output)  ! Formatting subroutine
        use classic_params
        use toc_types
        type(toc_descriptor_t),     intent(in)  :: key
        integer(kind=entry_length), intent(in)  :: ival
        character(len=*),           intent(out) :: output
        end subroutine p_format
      end interface
      logical,                intent(inout)         :: error        ! Logical error flag
    end subroutine toc_select_one
  end interface
  !
  interface
    function toc_select_keywords(keywords,toc,selected,error)
      use gbl_message
      use toc_types
      !---------------------------------------------------------------------
      ! @ private
      !  Identify the selected keywords and set up the internal pointers
      ! accordingly
      !---------------------------------------------------------------------
      integer(kind=4) :: toc_select_keywords  ! Function value on return
      character(len=*), intent(in)    :: keywords(:)  ! Keyword names
      type(toc_t),      intent(inout) :: toc          ! Table-Of-Content description
      integer(kind=4),  intent(out)   :: selected(:)  ! Keyword identifiers
      logical,          intent(inout) :: error        ! Logical error flag
    end function toc_select_keywords
  end interface
  !
  interface
    subroutine toc_select_do(rname,toc,key,ids,list,nelem,p_format,error)
      use toc_types
      !---------------------------------------------------------------------
      ! @ private
      !---------------------------------------------------------------------
      character(len=*),           intent(in)    :: rname
      type(toc_t),                intent(in)    :: toc
      type(toc_descriptor_t),     intent(inout) :: key
      integer(kind=4),            intent(in)    :: ids(key%select%nkey)  ! Key ids for this selection
      integer(kind=entry_length), intent(in)    :: nelem
      integer(kind=entry_length), intent(inout) :: list(2,nelem)
      interface
        subroutine p_format(key,ival,output)  ! Formatting subroutine
        use classic_params
        use toc_types
        type(toc_descriptor_t),     intent(in)  :: key
        integer(kind=entry_length), intent(in)  :: ival
        character(len=*),           intent(out) :: output
        end subroutine p_format
      end interface
      logical,                    intent(inout) :: error
    end subroutine toc_select_do
  end interface
  !
  interface
    subroutine toc_structure_parent(rname,name,error)
      use gbl_message
      use gkernel_types
      !---------------------------------------------------------------------
      ! @ private
      !  Define the Table-Of-Content Sic structure (parent structure part)
      !---------------------------------------------------------------------
      character(len=*), intent(in)    :: rname  ! Calling routine name
      character(len=*), intent(in)    :: name   ! Structure name e.g. MYTOC
      logical,          intent(inout) :: error  ! Logical error flag
    end subroutine toc_structure_parent
  end interface
  !
  interface
    subroutine toc_structure_key(rname,sname,key,twodims,error)
      use gildas_def
      use gbl_format
      use gbl_message
      use gkernel_types
      use toc_types
      !---------------------------------------------------------------------
      ! @ private
      !  Define the Table-Of-Content Sic structure (one key part)
      !---------------------------------------------------------------------
      character(len=*),       intent(in)    :: rname    ! Calling routine name
      character(len=*),       intent(in)    :: sname    ! Structure name e.g. MYTOC
      type(toc_descriptor_t), intent(in)    :: key      !
      logical,                intent(in)    :: twodims  ! Two dimensions for MYTOC%MSOUR?
      logical,                intent(inout) :: error    ! Logical error flag
    end subroutine toc_structure_key
  end interface
  !
end module classic_interfaces_private
