!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
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','[id]',&
         'Copy part of a cube header or data',&
         'This command uses an additive algorithm. It does nothing by&
         &default. The user has to explicitly define which part of the&
         &cube it wants to copy by raising the corresponding option.',&
         cubeedit_copy_command,&
         comm%comm,&
         error)
    if (error) return
    call stdarg%register(&
         'ID',&
         'Edited Identifier',&
         strg_id,&
         code_arg_optional,&
         error)
    if (error) return    
    ! Action
    call comm%all%register(&
         'ALL','Copy the header and the data',error)
    if (error) return
    call comm%head%register(&
         'HEADER','Copy the header',error)
    if (error) return
    call comm%data%register(&
         'DATA','Copy the data',error)
    if (error) return
    ! Input cube
    call comm%from%fully_register(&
         'FROM','[referenceid]',&
         'Define the reference cube to be copied',&
         strg_id,&
         'INPUT','Cube id from which to copy',&
         [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_cube_buffer
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    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 cubeedit_bufferlist_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
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
