module cubeio_interfaces_public
  interface
    subroutine cubeio_clone_cube_header(cubset,cubdef,hin,cout,error)
      use cubetools_access
      use cubetools_header_types
      use cubetools_setup_types
      use cubeio_header
      use cubeio_cube
      use cubeio_cube_define
      use cubeio_desc_setup
      use cubeio_messaging
      use cubeio_timing
      !---------------------------------------------------------------------
      ! @ public
      ! ZZZ RENAME THIS SUBROUTINE WHICH IS NOT A HGDF CLONING ANYMORE
      ! Prepare the GDF header according to input reference and optional
      ! changes
      !---------------------------------------------------------------------
      type(cube_setup_t),  intent(in)    :: cubset
      type(cube_define_t), intent(in)    :: cubdef
      type(cube_header_t), intent(in)    :: hin
      type(cubeio_cube_t), intent(inout) :: cout
      logical,             intent(inout) :: error
    end subroutine cubeio_clone_cube_header
  end interface
  !
  interface
    subroutine cubeio_create_hgdf(header,desc,oorder,hgdf,error)
      use image_def
      use cubetools_header_types
      use cubeio_header
      use cubeio_desc
      use cubeio_cube
      use cubeio_messaging
      !---------------------------------------------------------------------
      ! @ public
      ! Create or recreate the hgdf by converting the header with requested
      ! order.
      !---------------------------------------------------------------------
      type(cube_header_t),  intent(in)    :: header
      type(cubeio_desc_t),  intent(in)    :: desc
      integer(kind=code_k), intent(in)    :: oorder
      type(gildas),         intent(inout) :: hgdf
      logical,              intent(inout) :: error
    end subroutine cubeio_create_hgdf
  end interface
  !
  interface
    subroutine cubeio_create_cube_data(rname,cubset,cubdef,head,cub,error)
      use cubefitsio_image_write
      use cubetools_header_types
      use cubetools_setup_types
      use cubeio_block
      use cubeio_range
      use cubeio_cube
      use cubeio_cube_define
      use cubeio_header
      use cubeio_messaging
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      character(len=*),    intent(in)    :: rname
      type(cube_setup_t),  intent(in)    :: cubset
      type(cube_define_t), intent(in)    :: cubdef
      type(cube_header_t), intent(in)    :: head
      type(cubeio_cube_t), intent(inout) :: cub
      logical,             intent(inout) :: error
    end subroutine cubeio_create_cube_data
  end interface
  !
  interface
    subroutine cubeio_dump_cube(cubset,cubdef,head,cub,error)
      use cubetools_header_types
      use cubetools_setup_types
      use cubeio_messaging
      use cubeio_cube_define
      use cubeio_cube
      use cubeio_desc_setup
      !---------------------------------------------------------------------
      ! @ public
      ! Dump (i.e. write or update) a cube from memory to disk, if relevant
      ! (i.e. nothing done for a read-only cube).
      !---------------------------------------------------------------------
      type(cube_setup_t),  intent(in)    :: cubset
      type(cube_define_t), intent(in)    :: cubdef
      type(cube_header_t), intent(in)    :: head
      type(cubeio_cube_t), intent(inout) :: cub
      logical,             intent(inout) :: error
    end subroutine cubeio_dump_cube
  end interface
  !
  interface
    subroutine cubeio_iterate_chan(cubset,cubdef,head,cub,fchan,lchan,error)
      use cubetools_header_types
      use cubetools_setup_types
      use cubeio_cube_define
      use cubeio_cube
      use cubeio_messaging
      !---------------------------------------------------------------------
      ! @ public
      ! Prepare buffers for working (at least) on the requested channel
      ! range
      !---------------------------------------------------------------------
      type(cube_setup_t),   intent(in)    :: cubset
      type(cube_define_t),  intent(in)    :: cubdef
      type(cube_header_t),  intent(in)    :: head
      type(cubeio_cube_t),  intent(inout) :: cub
      integer(kind=chan_k), intent(in)    :: fchan
      integer(kind=chan_k), intent(in)    :: lchan
      logical,              intent(inout) :: error
    end subroutine cubeio_iterate_chan
  end interface
  !
  interface
    subroutine cubeio_iterate_pix(cubset,cubdef,head,cub,fypix,lypix,error)
      use cubetools_header_types
      use cubetools_setup_types
      use cubeio_cube_define
      use cubeio_cube
      use cubeio_messaging
      !---------------------------------------------------------------------
      ! @ public
      ! Prepare buffers for working (at least) on the requested Y pixel row
      ! range
      !---------------------------------------------------------------------
      type(cube_setup_t),   intent(in)    :: cubset
      type(cube_define_t),  intent(in)    :: cubdef
      type(cube_header_t),  intent(in)    :: head
      type(cubeio_cube_t),  intent(inout) :: cub
      integer(kind=pixe_k), intent(in)    :: fypix
      integer(kind=pixe_k), intent(in)    :: lypix
      logical,              intent(inout) :: error
    end subroutine cubeio_iterate_pix
  end interface
  !
  interface
    subroutine cubeio_iterate_subcube(cubset,cubdef,head,cub,first,last,error)
      use cubetools_header_types
      use cubetools_setup_types
      use cubeio_cube_define
      use cubeio_cube
      use cubeio_messaging
      !---------------------------------------------------------------------
      ! @ public
      ! Prepare buffers for working (at least) on the requested range
      !---------------------------------------------------------------------
      type(cube_setup_t),   intent(in)    :: cubset
      type(cube_define_t),  intent(in)    :: cubdef
      type(cube_header_t),  intent(in)    :: head
      type(cubeio_cube_t),  intent(inout) :: cub
      integer(kind=data_k), intent(in)    :: first
      integer(kind=data_k), intent(in)    :: last
      logical,              intent(inout) :: error
    end subroutine cubeio_iterate_subcube
  end interface
  !
  interface
    subroutine cubeio_get_header(cubset,cubdef,head,cub,error)
      use cubetools_dataformat
      use cubetools_access
      use cubetools_header_types
      use cubetools_setup_types
      use cubeio_header
      use cubeio_cube_define
      use cubeio_cube
      use cubeio_desc_setup
      use cubeio_messaging
      !----------------------------------------------------------------------
      ! @ public
      ! Get the file header in the cube_header_t, derived from the file
      ! header on disk (whatever the file kind).
      ! Also set up the IO-descriptor internal structure.
      !----------------------------------------------------------------------
      type(cube_setup_t),  intent(in)    :: cubset
      type(cube_define_t), intent(in)    :: cubdef
      type(cube_header_t), intent(inout) :: head
      type(cubeio_cube_t), intent(inout) :: cub
      logical,             intent(inout) :: error
    end subroutine cubeio_get_header
  end interface
  !
  interface
    subroutine cubeio_transpose_cube_desc(cubset,cubdef,in,out,error)
      use cubetools_access
      use cubetools_setup_types
      use cubeio_messaging
      use cubeio_cube_define
      use cubeio_cube
      use cubeio_desc
      use cubeio_desc_setup
      !---------------------------------------------------------------------
      ! @ public
      ! Memory-to-memory transposition of the input 'cubeio_cube_t' into the
      ! output one
      !---------------------------------------------------------------------
      type(cube_setup_t),   intent(in)    :: cubset
      type(cube_define_t),  intent(in)    :: cubdef
      type(cubeio_cube_t),  intent(in)    :: in
      type(cubeio_cube_t),  intent(inout) :: out
      logical,              intent(inout) :: error
    end subroutine cubeio_transpose_cube_desc
  end interface
  !
  interface
    subroutine cubeio_get_cube_data(cubset,cubdef,cub,error)
      use cubetools_setup_types
      use cubeio_cube_define
      use cubeio_cube
      use cubeio_messaging
      !----------------------------------------------------------------------
      ! @ public
      ! Read or prepare the data of a cube
      !----------------------------------------------------------------------
      type(cube_setup_t),  intent(in)    :: cubset
      type(cube_define_t), intent(in)    :: cubdef
      type(cubeio_cube_t), intent(inout) :: cub
      logical,             intent(inout) :: error
    end subroutine cubeio_get_cube_data
  end interface
  !
  interface
    subroutine cubeio_max_chan_block(cubset,cub,blocksize,blockname,nchan,error)
      use cubeio_messaging
      use cubetools_format
      use cubetools_setup_types
      use cubeio_cube
      !---------------------------------------------------------------------
      ! @ public
      ! Return the maximum number of channels which can be used in a
      ! cube_block_t for cube given as argument
      !---------------------------------------------------------------------
      type(cube_setup_t),   intent(in)    :: cubset
      type(cubeio_cube_t),  intent(in)    :: cub
      real(kind=4),         intent(in)    :: blocksize  ! [Bytes]
      character(len=*),     intent(in)    :: blockname
      integer(kind=chan_k), intent(out)   :: nchan
      logical,              intent(inout) :: error
    end subroutine cubeio_max_chan_block
  end interface
  !
  interface
    subroutine cubeio_max_y_block(cubset,cub,blocksize,blockname,ny,error)
      use cubeio_messaging
      use cubetools_format
      use cubetools_setup_types
      use cubeio_cube
      !---------------------------------------------------------------------
      ! @ public
      ! Return the maximum number of Y rows which can be used in a
      ! cube_block_t for cube given as argument
      !---------------------------------------------------------------------
      type(cube_setup_t),   intent(in)    :: cubset
      type(cubeio_cube_t),  intent(in)    :: cub
      real(kind=4),         intent(in)    :: blocksize  ! [Bytes]
      character(len=*),     intent(in)    :: blockname
      integer(kind=pixe_k), intent(out)   :: ny
      logical,              intent(inout) :: error
    end subroutine cubeio_max_y_block
  end interface
  !
  interface
    subroutine cubeio_max_any_block(cubset,cub,blocksize,blockname,nplane,error)
      use cubeio_messaging
      use cubetools_format
      use cubetools_setup_types
      use cubeio_cube
      !---------------------------------------------------------------------
      ! @ public
      ! Return the maximum number of planes which can be used in a
      ! cube_block_t for cube given as argument
      !---------------------------------------------------------------------
      type(cube_setup_t),   intent(in)    :: cubset
      type(cubeio_cube_t),  intent(in)    :: cub
      real(kind=4),         intent(in)    :: blocksize  ! [Bytes]
      character(len=*),     intent(in)    :: blockname
      integer(kind=data_k), intent(out)   :: nplane
      logical,              intent(inout) :: error
    end subroutine cubeio_max_any_block
  end interface
  !
  interface
    subroutine cubeio_cube_finish(cubset,head,cub,error)
      use cubetools_dataformat
      use cubetools_header_types
      use cubetools_setup_types
      use cubefitsio_header_read
      use cubeio_block
      use cubeio_cube
      use cubeio_timing
      !---------------------------------------------------------------------
      ! @ public
      ! This subroutine is to be invoked once the cube is fully read or
      ! created or modified, to leave it in a 'better' state.
      !---------------------------------------------------------------------
      type(cube_setup_t),  intent(in)    :: cubset
      type(cube_header_t), intent(in)    :: head
      type(cubeio_cube_t), intent(inout) :: cub
      logical,             intent(inout) :: error
    end subroutine cubeio_cube_finish
  end interface
  !
end module cubeio_interfaces_public
