!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module cubeedit_get
  use cubetools_parameters
  use cubetools_structure
  use cubetools_userspace
  use cubesyntax_keyval_types
  use cubeedit_messaging
  use cubeedit_getdata
  use cubeedit_getheader_tool
  !
  public :: get
  private
  !
  type :: get_comm_t
     type(option_t), pointer  :: comm
     type(value_strg_comm_t)  :: edid
     type(userspace_opt_t)    :: into
     type(getheader_comm_t)   :: head
     type(getdata_comm_t)     :: data
   contains
     procedure, public  :: register => cubeedit_get_comm_register
     procedure, private :: parse    => cubeedit_get_comm_parse
     procedure, private :: main     => cubeedit_get_comm_main 
  end type get_comm_t
  type(get_comm_t) :: get
  !
  type :: get_user_t
     logical :: dolist = .false.
     type(value_strg_user_t) :: edid
     type(userspace_user_t)  :: into
     type(getheader_user_t)  :: head
     type(getdata_user_t)    :: data
   contains
     procedure, private :: toprog => cubeedit_get_user_toprog
  end type get_user_t
  !
  type :: get_prog_t
     character(len=varn_l)   :: edid = strg_unk
     !type(userspace_prog_t) :: into
     type(getheader_prog_t)  :: head
     !type(getdata_prog_t)   :: data
   contains
     procedure, private :: list => cubeedit_get_prog_act_list
     procedure, private :: get  => cubeedit_get_prog_act_get
  end type get_prog_t
  type(get_prog_t) :: get_prog
  !
contains
  !
  subroutine cubeedit_get_command(line,error)
    !-------------------------------------------------------------------
    ! Support routine for command GET
    !-------------------------------------------------------------------
    character(len=*), intent(in)    :: line
    logical,          intent(inout) :: error
    !
    type(get_user_t) :: user
    character(len=*), parameter :: rname='GET>COMMAND'
    !
    call cubeedit_message(edseve%trace,rname,'Welcome')
    !
    call get%parse(line,user,error)
    if (error) return
    call get%main(user,error)
    if (error) return
  end subroutine cubeedit_get_command
  !
  !----------------------------------------------------------------------
  !
  subroutine cubeedit_get_comm_register(comm,error)
    !-------------------------------------------------------------------
    ! Register GO\GET command and its keys
    !-------------------------------------------------------------------
    class(get_comm_t), intent(inout) :: comm
    logical,           intent(inout) :: error
    !
    logical, parameter :: iterator = .true.
    character(len=*), parameter :: rname='GET>COMM>REGISTER'
    !
    call cubeedit_message(edseve%trace,rname,'Welcome')
    !
    ! Syntax
    call cubetools_register_command(&
         'GET','[bufferid]',&
         'Get array or header information from an edited buffer',&
         'Get header and data information from an opened edited buffer into SIC&
         & variables. Without options, GET lists available header/data&
         & retrieval buffers.'//strg_bl//&
         'Behavior:'//strg_cr//&
         '- /INTO controls destination userspace; default parent structure&
         & name is EDITGET.'//strg_cr//&
         '- Header selectors (/AXIS, /SHAPE, /UNIT, /EXTREMA, /NOISE,&
         & /SPATIALFRAME, /SOURCE, /PTYPE, /PCENTER, /PANGLE, /BEAM,&
         & /SPECTRALFRAME, /VELOCITY, /REDSHIFT, /LINE, /FREQUENCY,&
         & /WAVELENGTH, /OBSERVATORY, /ID, /TUPLE, /PARENTS,&
         & /CHILDREN, /TWINS) fetch metadata fields.'//strg_cr//&
         '- Data selectors (/ZERO, /FIRST, /LAST, /NEXT, /PREVIOUS,&
         & /AFTERLAST, /CURRENT, /ENTRY, /PIXEL, /CHANNEL, /CUBE)&
         & choose data extraction mode.'//strg_cr//&
         '- Data selectors are mutually exclusive per command call.'//strg_bl//&
         'Notes:'//strg_cr//&
         '- GET is read-only. Use PUT to write modifications into an&
         & edited buffer.'//strg_cr//&
         '- The edited buffer is registered in the DAG only after CLOSE.'&
         //strg_cr//&
         '- Complex spectrum and complex full-cube fetch paths are&
         & unsupported.'//strg_bl//&
         'Examples:'//strg_cr//&
         'CUBE> GET'//strg_cr//&
         'CUBE> GET myedit /SHAPE /INTO info'//strg_cr//&
         'CUBE> GET myedit /CHANNEL 10 /INTO spec'//strg_bl//&
         'Typical workflow:'//strg_cr//&
         'CUBE> OPEN myedit /LIKE source_cube'//strg_cr//&
         'CUBE> GET myedit /SHAPE /INTO info'//strg_cr//&
         'CUBE> GET myedit /CHANNEL 10 /INTO spec'//strg_cr//&
         'CUBE> PUT myedit ...'//strg_bl//&
         'Use GET outputs as inspection inputs for later PUT updates.',&
         cubeedit_get_command,&
         comm%comm,&
         error)
    if (error) return
    call comm%edid%register(&
         'BUFFERID',&
         'Edited buffer identifier',&
         strg_star,&
         code_arg_optional,&
         strg_emp,&
         error)
    if (error) return
    call get%into%register(error)
    if (error) return
    call get%head%register(get_prog%edid,get%into,error)
    if (error) return
    call get%data%register(get%into,access_is_fixed,iterator,error)
    if (error) return
  end subroutine cubeedit_get_comm_register
  !
  subroutine cubeedit_get_comm_parse(comm,line,user,error)
    !-------------------------------------------------------------------
    ! 
    !-------------------------------------------------------------------
    class(get_comm_t), intent(in)    :: comm
    character(len=*),  intent(in)    :: line
    type(get_user_t),  intent(inout) :: user
    logical,           intent(inout) :: error
    !
    character(len=*), parameter :: rname='GET>COMM>PARSE'
    !
    call cubeedit_message(edseve%trace,rname,'Welcome')
    !
    if (cubetools_nopt().eq.0) then
       user%dolist = .true.
    else
       user%dolist = .false.
       call comm%edid%parse(line,comm%comm,user%edid,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 cubeedit_get_comm_parse
  !
  subroutine cubeedit_get_comm_main(comm,user,error)
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(get_comm_t), intent(in)    :: comm
    type(get_user_t),  intent(in)    :: user
    logical,           intent(inout) :: error
    !
    type(get_prog_t) :: prog
    character(len=*), parameter :: rname='GET>COMM>MAIN'
    !
    call cubeedit_message(edseve%trace,rname,'Welcome')
    !
    if (user%dolist) then
       call prog%list(error)
       if (error) return
       !***JP: The following one should be transfered to cubeedit_get_prog_list after standardization of cubeedit_getdata
       call comm%data%list(error)
       if (error) return
    else
       call user%toprog(comm,prog,error)
       if (error) return
       call prog%get(comm,user,error)
       if (error) return
    endif
  end subroutine cubeedit_get_comm_main
  !
  !------------------------------------------------------------------------
  !
  subroutine cubeedit_get_user_toprog(user,comm,prog,error)
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(get_user_t), intent(in)    :: user
    type(get_comm_t),  intent(in)    :: comm    
    type(get_prog_t),  intent(out)   :: prog
    logical,           intent(inout) :: error
    !
    character(len=*), parameter :: rname='GET>USER>TOPROG'
    !
    call cubeedit_message(edseve%trace,rname,'Welcome')
    !
    call user%edid%toprog(comm%edid,prog%edid,error)
    if (error) return    
    call user%head%toprog(comm%head,'EDITGET',user%data%do,prog%head,error)
    if (error) return
  end subroutine cubeedit_get_user_toprog
  !
  !------------------------------------------------------------------------
  !
  subroutine cubeedit_get_prog_act_list(prog,error)
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(get_prog_t), intent(in)    :: prog
    logical,           intent(inout) :: error
    !
    character(len=*), parameter :: rname='GET>PROG>ACT>LIST'
    !
    call cubeedit_message(edseve%trace,rname,'Welcome')
    !
    call prog%head%list(error)
    if (error) return
    !call prog%data%list(error)
    !if (error) return
  end subroutine cubeedit_get_prog_act_list
  !
  subroutine cubeedit_get_prog_act_get(prog,comm,user,error)
    use cube_types
    use cubeedit_opened_types
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(get_prog_t), intent(inout) :: prog
    type(get_comm_t),  intent(in)    :: comm    
    type(get_user_t),  intent(in)    :: user !***JP: Should be removed
    logical,           intent(inout) :: error
    !
    integer(kind=entr_k) :: ie
    type(cube_t), pointer :: cube
    character(len=*), parameter :: rname='GET>PROG>ACT>GET'
    !
    call cubeedit_message(edseve%trace,rname,'Welcome')
    !
    call opened%get_cube_pointer(prog%edid,cube,error)
    if (error) return
    ! As of today, data access can only be done on a cube_t. But header
    ! access can be done on any format_t
    prog%head%cube => cube
    call prog%head%get(error)
    if (error) return
    if (user%data%do) then
       call opened%get_cube_entry(prog%edid,ie,error)
       if (error) return   
       call comm%data%get(user%data,cube,'EDITGET',user%head%present,ie,error)
       if (error) return
       call opened%set_cube_entry(prog%edid,ie,error)
       if (error) return   
    endif
  end subroutine cubeedit_get_prog_act_get
end module cubeedit_get
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
