module cubeio_desc
  use cubetools_parameters
  !
  type cubeio_desc_t
    ! Elements intrinsic to the data
    integer(kind=code_k) :: order = code_null   ! Data is ordered LMV or VLM?
    logical              :: iscplx = .false.    ! R*4 or C*4?
    integer(kind=data_k) :: n1 = 0              ! Size of 1st dimension
    integer(kind=data_k) :: n2 = 0              ! Size of 2nd dimension
    integer(kind=data_k) :: n3 = 0              ! Size of 3rd dimension
    integer(kind=pixe_k) :: nx = 0              ! Number of X pixels
    integer(kind=pixe_k) :: ny = 0              ! Number of Y pixels
    integer(kind=chan_k) :: nc = 0              ! Number of channels
    ! Elements external to the data, redefinable before any access to the cube
    integer(kind=code_k)  :: access = code_null             ! Data access mode (e.g. image/spectrum)
    integer(kind=4)       :: buffered = code_buffer_none    ! Data buffering kind
    integer(kind=4)       :: action = code_null             ! Data action mode (read/write/update)
    integer(kind=4)       :: unblank = code_null            ! Data unblank mode at read time (none/error/patch)
    logical               :: reblank = .false.              ! Data reblank mode at write time
    real(kind=4)          :: bval,eval                      ! Blanking values if reblank is .true.
  contains
    ! final :: cubeio_desc_final  ! Can not be done implicitly as other components rely on the descriptor
  end type cubeio_desc_t

  public :: cubeio_desc_t
  public :: cubeio_desc_reset,cubeio_desc_transpose,cubeio_desc_final
  private

contains

  subroutine cubeio_desc_reset(desc,error)
    type(cubeio_desc_t), intent(out)   :: desc
    logical,             intent(inout) :: error
    ! All done by intent(out)
    return
  end subroutine cubeio_desc_reset

  subroutine cubeio_desc_transpose(in,out,oaccess,error)
    use cubetools_access
    type(cubeio_desc_t),  intent(in)    :: in
    type(cubeio_desc_t),  intent(inout) :: out
    integer(kind=code_k), intent(in)    :: oaccess
    logical,              intent(inout) :: error
    !
    ! This is generic, even if already in correct access
    call cubeio_desc_copy(in,out,error)
    if (error)  return
    out%access = oaccess
    out%order = cubetools_access2order(oaccess)
  end subroutine cubeio_desc_transpose

  subroutine cubeio_desc_copy(in,out,error)
    type(cubeio_desc_t), intent(in)    :: in
    type(cubeio_desc_t), intent(inout) :: out
    logical,             intent(inout) :: error
    out = in
  end subroutine cubeio_desc_copy

  subroutine cubeio_desc_final(desc)
    !---------------------------------------------------------------------
    ! Finalize a 'cubeio_desc_t' instance
    !---------------------------------------------------------------------
    type(cubeio_desc_t), intent(inout) :: desc
    !
    ! Nothing to be freed
  end subroutine cubeio_desc_final

end module cubeio_desc
