!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module cubego_load
  use cubetools_parameters
  use cube_types
  use cubetools_structure
  use cubetools_userspace
  use cubeadm_cubeid_types
  use cubego_messaging
  use cubeedit_getdata
  use cubeedit_getheader_tool
  !
  public :: load
  private
  !
  type :: load_comm_t
     type(option_t),     pointer :: comm
     type(cubeid_arg_t), pointer :: cube
     type(userspace_opt_t)       :: into
     type(getheader_comm_t)      :: head
     type(getdata_comm_t)        :: data
   contains
     procedure, public  :: register => cubego_load_comm_register
     procedure, private :: parse    => cubego_load_comm_parse
     procedure, private :: main     => cubego_load_comm_main
  end type load_comm_t
  type(load_comm_t) :: load
  !
  type :: load_user_t
     logical :: dolist = .false.
     type(cubeid_user_t)    :: cubeids
     type(userspace_user_t) :: into
     type(getheader_user_t) :: head
     type(getdata_user_t)   :: data
   contains
     procedure, private :: toprog => cubego_load_user_toprog
  end type load_user_t
  !
  type :: load_prog_t
     type(cube_t), pointer    :: cube
     !type(userspace_prog_t)  :: into
     type(getheader_prog_t)   :: head
     !type(getdata_prog_t)    :: data
   contains
     procedure, private :: list => cubego_load_prog_act_list
     procedure, private :: load => cubego_load_prog_act_load
  end type load_prog_t
  !
contains
  !
  subroutine cubego_load_command(line,error)
    !----------------------------------------------------------------------
    ! Support routine for command LOAD
    !----------------------------------------------------------------------
    character(len=*), intent(in)    :: line
    logical,          intent(inout) :: error
    !
    type(load_user_t) :: user
    character(len=*), parameter :: rname='LOAD>COMMAND'
    !
    call cubego_message(goseve%trace,rname,'Welcome')
    !
    call load%parse(line,user,error)
    if (error) return
    call load%main(user,error)
    if (error) return
  end subroutine cubego_load_command
  !
  !----------------------------------------------------------------------
  !
  subroutine cubego_load_comm_register(comm,error)
    use cubedag_allflags
    !-------------------------------------------------------------------
    ! Register GO\LOAD command and its keys
    !-------------------------------------------------------------------
    class(load_comm_t), intent(inout) :: comm
    logical,            intent(inout) :: error
    !
    type(cubeid_arg_t) :: incube
    logical, parameter :: noiterator = .false.
    character(len=*), parameter :: rname='LOAD>COMM>REGISTER'
    !
    call cubego_message(goseve%trace,rname,'Welcome')
    !
    ! Syntax
    call cubetools_register_command(&
         'LOAD','[cubeid]',&
         'Load array or header information from a cube',&
         'Map cube header or data information into SIC variables for&
         & inspection.'//strg_bl//&
         'Behavior:'//strg_cr//&
         '- With no option, the command lists available header and data&
         & information extracted in SIC variables.'//strg_cr//&
         '- Else, the command resolves the input cubeid, variable name,&
         & and delegated header/data loaders.'//strg_cr//&
         '- Data selectors are mutually exclusive in one call (/FIRST,&
         & /LAST, /ENTRY, /PIXEL, /CHANNEL, /CUBE).'//strg_bl//&
         'Notes:'//strg_cr//&
         '- Mapped values are informational and do not modify cube&
         & content.'//strg_cr//&
         '- Use EDIT commands when cube values or headers must be&
         & modified.'//strg_bl//&
         'Examples:'//strg_cr//&
         '  CUBE> LOAD c1 /SHAPE /INTO n'//strg_cr//&
         '  CUBE> LOAD c1 /PIXEL 10 20 relative /INTO spec'//strg_bl//&
         'Typical workflow:'//strg_cr//&
         '  CUBE> LOAD'//strg_cr//&
         '  CUBE> LOAD c1 /AXIS VELOCITY RELATIVE km/s /INTO axis'//strg_cr//&
         '  CUBE> LOAD c1 /ENTRY 12 IMAGE /INTO slice',&
         cubego_load_command,&
         comm%comm,&
         error)
    if (error) return
    call incube%register(&
         'CUBEID',&
         'Identity of the source cube used for loading',&
         'If omitted, use the last matching cube (any family/flags) in&
         & the default index (DAG by default; see SET\INDEX).',&
         code_arg_optional,&
         [flag_any],&
         code_read,&
         code_access_imaset_or_speset,&
         comm%cube,&
         error)
    if (error) return
    !
    call comm%into%register(error)
    if (error) return
    call comm%head%register('GOLOAD',load%into,error)
    if (error) return
    call comm%data%register(load%into,access_not_fixed,noiterator,error)
    if (error) return
  end subroutine cubego_load_comm_register
  !
  subroutine cubego_load_comm_parse(comm,line,user,error)
    !-------------------------------------------------------------------
    !
    !-------------------------------------------------------------------
    class(load_comm_t), intent(in)    :: comm
    character(len=*),   intent(in)    :: line
    type(load_user_t),  intent(inout) :: user
    logical,            intent(inout) :: error
    !
    character(len=*), parameter :: rname='LOAD>COMM>PARSE'
    !
    if (cubetools_nopt().eq.0) then
       user%dolist = .true.
    else
       user%dolist = .false.
       call cubeadm_cubeid_parse(line,comm%comm,user%cubeids,error)
       if (error) return
       call comm%into%parse(line,user%into,error)
       if (error) return
       call comm%head%parse(line,user%into,user%head,error)
       if (error) return
       call comm%data%parse(line,user%into,user%data,error)
       if (error) return
    endif
  end subroutine cubego_load_comm_parse
  !
  subroutine cubego_load_comm_main(comm,user,error)
    !-------------------------------------------------------------------
    !
    !-------------------------------------------------------------------
    class(load_comm_t), intent(in)    :: comm
    type(load_user_t),  intent(in)    :: user
    logical,            intent(inout) :: error
    !
    type(load_prog_t) :: prog
    character(len=*), parameter :: rname='LOAD>COMM>MAIN'
    !
    if (user%dolist) then
       call prog%list(error)
       if (error) return
       !***JP: The following one should be transfered to cubego_load_prog_list after standardization of cubedit_getdata
       call comm%data%list(error)
       if (error) return
    else
       call user%toprog(comm,prog,error)
       if (error) return
       call prog%load(comm,user,error)
       if (error) return
    endif
  end subroutine cubego_load_comm_main
  !
  !------------------------------------------------------------------------
  !
  subroutine cubego_load_user_toprog(user,comm,prog,error)
    use cubeadm_get
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(load_user_t), intent(in)    :: user
    type(load_comm_t),  intent(in)    :: comm    
    type(load_prog_t),  intent(out)   :: prog
    logical,            intent(inout) :: error
    !
    character(len=*), parameter :: rname='LOAD>USER>TOPROG'
    !
    call cubego_message(goseve%trace,rname,'Welcome')
    !
    ! As of today, data access can only be done on a cube_t
    call cubeadm_get_header(comm%cube,user%cubeids,prog%cube,error)
    if (error) return
    ! But header access can be done on any format_t    
    call cubeadm_get_fheader(comm%cube,user%cubeids,prog%head%cube,error)
    if (error) return
    call user%head%toprog(comm%head,'LOADEDIT',user%data%do,prog%head,error)
    if (error) return
  end subroutine cubego_load_user_toprog
  !
  !------------------------------------------------------------------------
  !
  subroutine cubego_load_prog_act_list(prog,error)
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(load_prog_t), intent(in)    :: prog
    logical,            intent(inout) :: error
    !
    character(len=*), parameter :: rname='LOAD>PROG>ACT>LIST'
    !
    call cubego_message(goseve%trace,rname,'Welcome')
    !
    call prog%head%list(error)
    if (error) return
    !call prog%data%list(error)
    !if (error) return
  end subroutine cubego_load_prog_act_list
  !
  subroutine cubego_load_prog_act_load(prog,comm,user,error)
    use cube_types
    use cubeadm_opened
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(load_prog_t), intent(inout) :: prog
    type(load_comm_t),  intent(in)    :: comm
    type(load_user_t),  intent(in)    :: user !***JP: Should be removed
    logical,            intent(inout) :: error
    !
    integer(kind=entr_k) :: ie
    type(cubeadm_iterator_t) :: iter
    character(len=*), parameter :: rname='LOAD>PROG>ACT>LOAD'
    !
    call cubego_message(goseve%trace,rname,'Welcome')
    !
    if (user%data%do) then
       ! Do not forget to prepare the internal iterator so that
       ! getting image/channel/etc... works properly.
       call cubeadm_datainit_all(iter,error)
       if (error) return
       ie = entr_unk
       call comm%data%get(user%data,prog%cube,'GOLOAD',user%head%present,ie,error)
       if (error) return
    endif
    call prog%head%get(error)
    if (error) return
  end subroutine cubego_load_prog_act_load
end module cubego_load
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
