!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module cubeedit_copy
  use cubetools_parameters
  use cube_types
  use cubetools_structure
  use cubesyntax_key_types
  use cubeadm_ancillary_cube_types
  use cubeedit_messaging
  !
  public :: copy
  private
  !
  type :: copy_comm_t
     type(option_t), pointer :: comm
     type(key_comm_t) :: all
     type(key_comm_t) :: head
     type(key_comm_t) :: data
     type(ancillary_cube_comm_t) :: from
   contains
     procedure, public  :: register => cubeedit_copy_comm_register
     procedure, private :: parse    => cubeedit_copy_comm_parse
     procedure, private :: main     => cubeedit_copy_comm_main
  end type copy_comm_t
  type(copy_comm_t) :: copy  
  !
  type copy_user_t
     character(len=argu_l)  :: id
     type(key_user_t) :: all
     type(key_user_t) :: head
     type(key_user_t) :: data
     type(ancillary_cube_user_t) :: from
   contains
     procedure, private :: toprog => cubeedit_copy_user_toprog
  end type copy_user_t
  !
  type copy_prog_t
     type(cube_t), pointer :: edited
     type(key_prog_t) :: all
     type(key_prog_t) :: head
     type(key_prog_t) :: data
     type(ancillary_cube_prog_t) :: from
   contains
     procedure, private :: header => cubeedit_copy_prog_header
  end type copy_prog_t
  !
contains
  !
  subroutine cubeedit_copy_command(line,error)
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    character(len=*), intent(in)    :: line
    logical,          intent(inout) :: error
    !
    type(copy_user_t) :: user
    character(len=*), parameter :: rname='COPY>COMMAND'
    !
    call cubeedit_message(edseve%trace,rname,'Welcome')
    !
    call copy%parse(line,user,error)
    if (error) return
    call copy%main(user,error)
    if (error) continue
  end subroutine cubeedit_copy_command
  !
  !----------------------------------------------------------------------
  !
  subroutine cubeedit_copy_comm_register(comm,error)
    use cubedag_allflags
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(copy_comm_t), intent(inout) :: comm
    logical,            intent(inout) :: error
    !
    type(standard_arg_t) :: stdarg
    character(len=*), parameter :: rname='COPY>COMM>REGISTER'
    !
    call cubeedit_message(edseve%trace,rname,'Welcome')
    !
    ! Syntax
    call cubetools_register_command(&
         'COPY','[bufferid]',&
         'Copy part of a cube header or data',&
         'Copy selected parts of a reference cube into an opened edited buffer.&
         & COPY is additive: nothing is copied unless at least one copy&
         & key is enabled.'//strg_bl//&
         'Behavior:'//strg_cr//&
         '- COPY resolves the edited buffer from bufferid (or the current&
         & edited buffer identifier) and uses /FROM INPUT as reference&
         & source.'//strg_cr//&
         '- COPY applies requested transfers to the edited buffer.&
         & The edited buffer is registered in the DAG only after CLOSE.'&
         //strg_cr//&
         '- Current implementation transfers header metadata only.&
         & Data-value transfer is not implemented yet.'//strg_bl//&
         'Notes:'//strg_cr//&
         '- If no copy key is enabled, COPY performs no transfer.'//strg_bl//&
         'Examples:'//strg_cr//&
         'CUBE> COPY myedit /FROM ref_cube /ALL'//strg_cr//&
         'CUBE> COPY myedit /FROM ref_cube /HEADER'//strg_cr//&
         'CUBE> COPY myedit /FROM ref_cube /DATA'//strg_bl//&
         'Typical workflow:'//strg_cr//&
         'CUBE> OPEN myedit /LIKE ref_cube'//strg_cr//&
         'CUBE> COPY myedit /FROM ref_cube /HEADER'//strg_cr//&
         'CUBE> CLOSE myedit'//strg_bl//&
         'The edited buffer is registered in the DAG only after CLOSE.',&
         cubeedit_copy_command,&
         comm%comm,&
         error)
    if (error) return
    call stdarg%register(&
         'BUFFERID',&
         'Edited buffer identifier',&
         strg_emp,&
         code_arg_optional,&
         error)
    if (error) return    
    ! Action
    call comm%all%register(&
         'ALL',&
         'Request header and data copy',&
         'Enable both /HEADER and /DATA copy requests in one command.&
         & With current implementation, this yields header copy only&
         & because data-value transfer is not implemented.',&
         error)
    if (error) return
    call comm%head%register(&
         'HEADER',&
         'Request header copy',&
         'Copy header metadata from the /FROM reference cube into the&
         & opened edited buffer.',&
         error)
    if (error) return
    call comm%data%register(&
         'DATA',&
         'Request data copy',&
         'Request data-value copy from the /FROM reference cube. The key&
         & is accepted but current implementation does not transfer data&
         & values.',&
         error)
    if (error) return
    ! Input cube
    call comm%from%fully_register(&
         'FROM','[referenceid]',&
         'Select the reference cube to copy from',&
         strg_emp,&
         'INPUT',&
         'Reference cube id used as COPY source',&
         [flag_any],&
         code_arg_mandatory,&
         code_read,&
         code_access_any,& !***JP: For data it's not so simple!
         error)
    if (error) return
  end subroutine cubeedit_copy_comm_register
  !
  subroutine cubeedit_copy_comm_parse(comm,line,user,error)
    !----------------------------------------------------------------------
    ! COPY /HEADER /DATA
    !----------------------------------------------------------------------
    class(copy_comm_t), intent(in)    :: comm
    character(len=*),   intent(in)    :: line
    type(copy_user_t),  intent(out)   :: user
    logical,            intent(inout) :: error
    !
    character(len=*), parameter :: rname='COPY>COMM>PARSE'
    !
    call cubeedit_message(edseve%trace,rname,'Welcome')
    !
    user%id = strg_star
    call cubetools_getarg(line,comm%comm,1,user%id,.not.mandatory,error)
    if (error) return
    !
    call comm%all%parse(line,user%all,error)
    if (error) return
    call comm%head%parse(line,user%head,error)
    if (error) return
    call comm%data%parse(line,user%data,error)
    if (error) return
    call comm%from%parse(line,user%from,error)
    if (error) return
  end subroutine cubeedit_copy_comm_parse
  !
  subroutine cubeedit_copy_comm_main(comm,user,error)
    use cubeadm_timing
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(copy_comm_t), intent(in)    :: comm
    type(copy_user_t),  intent(inout) :: user
    logical,            intent(inout) :: error
    !
    type(copy_prog_t) :: prog
    character(len=*), parameter :: rname='COPY>MAIN'
    !
    call cubeedit_message(edseve%trace,rname,'Welcome')
    !
    call user%toprog(comm,prog,error)
    if (error) return
    call prog%header(comm,error)
    if (error) return
  end subroutine cubeedit_copy_comm_main
  !
  !----------------------------------------------------------------------
  !
  subroutine cubeedit_copy_user_toprog(user,comm,prog,error)
    use cubeedit_opened_types
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(copy_user_t), intent(in)    :: user
    type(copy_comm_t),  intent(in)    :: comm
    type(copy_prog_t),  intent(out)   :: prog
    logical,            intent(inout) :: error
    !
    character(len=*), parameter :: rname='COPY>USER>TOPROG'
    !
    call cubeedit_message(edseve%trace,rname,'Welcome')
    !
    call opened%get_cube_pointer(user%id,prog%edited,error)
    if (error) return
    !
    call user%from%toprog(comm%from,prog%from,error)
    if (error) return
    call user%all%toprog(comm%all,prog%all,error)
    if (error) return
    call user%head%toprog(comm%head,prog%head,error)
    if (error) return
    call user%data%toprog(comm%data,prog%data,error)
    if (error) return
    ! Analyse user input
    if (prog%all%act) then
       prog%head%act = .true.
       prog%data%act = .true.
    endif
    ! User feedback about the interpretation of his command line
    if (prog%head%act) call cubeedit_message(seve%r,rname,'Copying header')
    if (prog%data%act) call cubeedit_message(seve%r,rname,'Copying data')
  end subroutine cubeedit_copy_user_toprog
  !
  !----------------------------------------------------------------------
  !
  subroutine cubeedit_copy_prog_header(prog,comm,error)
    use cubetools_header_types
    use cubetools_header_interface
    use cubetools_observatory_types
    !----------------------------------------------------------------------
    ! The array section of the header is only copied when the data is
    ! copied!
    !----------------------------------------------------------------------
    class(copy_prog_t), intent(inout) :: prog
    type(copy_comm_t),  intent(in)    :: comm
    logical,            intent(inout) :: error
    !
    type(cube_header_interface_t) :: inhead,ouhead
    character(len=*), parameter :: rname='COPY>PROG>HEADER'
    !
    call cubeedit_message(edseve%trace,rname,'Welcome')
    !
    if (prog%head%act) then
       call cubetools_header_export(prog%from%cube%head,inhead,error)
       if (error) return
       call cubetools_header_export(prog%edited%head,ouhead,error)
       if (error) return
       call inhead%axset_copyto(ouhead,error)
       if (error) return
       call inhead%spatial_copyto(ouhead,error)
       if (error) return
       call inhead%spectral_copyto(ouhead,error)
       if (error) return
       call cubetools_observatory_copy(inhead%obs,ouhead%obs,error)
       if (error) return
       call cubetools_header_import_and_derive(ouhead,prog%edited%head,error)
       if (error) return
    endif
  end subroutine cubeedit_copy_prog_header
end module cubeedit_copy
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
