!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module cubeset_timing
  use cubetools_structure
  use cubesyntax_key_types
  use cubetools_switch_types
  use cubeset_messaging
  !
  public :: timing
  private
  !
  type :: timing_comm_t
     type(option_t), pointer :: comm
     type(switch_comm_t) :: io
     type(switch_comm_t) :: execution
     type(key_comm_t)    :: default
   contains
     procedure, public  :: register => cubeset_timing_register
     procedure, private :: parse    => cubeset_timing_parse
     procedure, private :: main     => cubeset_timing_main
  end type timing_comm_t
  type(timing_comm_t) :: timing
  !
  type :: timing_user_t
     logical :: list
     type(switch_user_t) :: io
     type(switch_user_t) :: execution
     type(key_user_t)    :: default
   contains
     procedure, private :: toprog => cubeset_timing_user_toprog
  end type timing_user_t
  !
  type :: timing_prog_t
     logical :: list
     type(switch_prog_t) :: io
     type(switch_prog_t) :: execution
     type(key_prog_t)    :: default
   contains
     procedure, private :: act => cubeset_timing_prog_act
  end type timing_prog_t
  !
contains
  !
  subroutine cubeset_timing_command(line,error)
    !---------------------------------------------------------------------
    ! 
    !---------------------------------------------------------------------
    character(len=*), intent(in)    :: line
    logical,          intent(inout) :: error
    !
    type(timing_user_t) :: user
    character(len=*), parameter :: rname='TIMING>COMMAND'    
    !
    call cubeset_message(setseve%trace,rname,'Welcome')
    !
    call timing%parse(line,user,error)
    if (error) return
    call timing%main(user,error)
    if (error) return
  end subroutine cubeset_timing_command
  !  
  !----------------------------------------------------------------------
  !
  subroutine cubeset_timing_register(timing,error)
    use cubetools_parameters
    !---------------------------------------------------------------------
    ! 
    !---------------------------------------------------------------------
    class(timing_comm_t), intent(inout) :: timing
    logical,              intent(inout) :: error
    !
    character(len=*), parameter :: rname='TIMING>REGISTER'
    !
    call cubeset_message(setseve%trace,rname,'Welcome')
    !
    call cubetools_register_command(&
         'TIMING','',&
         'Enable or disable timing feedback at the end of processing',&
         'Default is OFF. Two topics are available: /EXECUTION for&
         & execution times, and /IO for data Input and Output,&
         & Default values can be reset with option /DEFAULT. TIMING&
         & without any options displays the current timing setup.&
         & When /DEFAULT is combined with other keys on the same command&
         & line, reset is applied first.',&
         cubeset_timing_command,&
         timing%comm,&
         error)
    if (error) return
    !
    call timing%io%register(&
         'IO',&
         'IO timing',&
         'OFF',&
         strg_emp,&
         error)
    if (error) return
    !
    call timing%execution%register(&
         'EXECUTION',&
         'execution timing',&
         'OFF',&
         strg_emp,&
         error)
    if (error) return
    !
    call timing%default%register(&
         'DEFAULT',&
         'Reset settings',&
         'Reset timing settings before applying other keys from the same&
         & command line.',&
         error)
    if (error) return
  end subroutine cubeset_timing_register
  !
  subroutine cubeset_timing_parse(comm,line,user,error)
    use cubeadm_setup
    !---------------------------------------------------------------------
    !
    !---------------------------------------------------------------------
    class(timing_comm_t), intent(inout) :: comm
    character(len=*),     intent(in)    :: line
    type(timing_user_t),  intent(out)   :: user
    logical,              intent(inout) :: error
    !
    character(len=*), parameter :: rname='TIMING>PARSE'
    !
    call cubeset_message(setseve%trace,rname,'Welcome')
    !
    user%list = cubetools_nopt().eq.0
    !
    if (user%list) then
       ! nothing to do
    else
       call comm%io%parse(line,user%io,error)
       if (error) return
       call comm%execution%parse(line,user%execution,error)
       if (error) return
       call comm%default%parse(line,user%default,error)
       if (error) return
    endif
  end subroutine cubeset_timing_parse
  !
  subroutine cubeset_timing_main(comm,user,error)
    use cubeadm_setup
    !---------------------------------------------------------------------
    !
    !---------------------------------------------------------------------
    class(timing_comm_t), intent(inout) :: comm
    type(timing_user_t),  intent(in)    :: user
    logical,              intent(inout) :: error
    !
    type(timing_prog_t) :: prog
    character(len=*), parameter :: rname='TIMING>MAIN'
    !
    call cubeset_message(setseve%trace,rname,'Welcome')
    !
    call user%toprog(comm,prog,error)
    if (error) return
    call prog%act(error)
    if (error) return
  end subroutine cubeset_timing_main
  !
  !-----------------------------------------------------------------------
  !
  subroutine cubeset_timing_user_toprog(user,comm,prog,error)
    !---------------------------------------------------------------------
    !
    !---------------------------------------------------------------------
    class(timing_user_t), intent(in)    :: user
    type(timing_comm_t),  intent(in)    :: comm
    type(timing_prog_t),  intent(inout) :: prog
    logical,              intent(inout) :: error
    !
    character(len=*), parameter :: rname='TIMING>USER>TOPROG'
    !
    call cubeset_message(setseve%trace,rname,'Welcome')
    !
    prog%list = user%list
    call user%io%toprog(comm%io,prog%io,error)
    if (error) return
    call user%execution%toprog(comm%execution,prog%execution,error)
    if (error) return
    call user%default%toprog(comm%default,prog%default,error)
    if (error) return
  end subroutine cubeset_timing_user_toprog
  !
  !-----------------------------------------------------------------------
  !
  subroutine cubeset_timing_prog_act(prog,error)
    use cubetools_setup_types
    !---------------------------------------------------------------------
    !
    !---------------------------------------------------------------------
    class(timing_prog_t), intent(inout) :: prog
    logical,              intent(inout) :: error
    !
    character(len=*), parameter :: rname='TIMING>PROG>ACT'
    type(cube_setup_api_t) :: setup
    !
    call cubeset_message(setseve%trace,rname,'Welcome')
    !
    if (prog%default%act)   call setup%timing%reset()
    if (prog%io%act)        call setup%timing%io%set(prog%io%enabled,error)
    if (prog%execution%act) call setup%timing%command%set(prog%execution%enabled,error)
    if (prog%list) then
       call cubeset_message(seve%r,rname,'  Timing')
       prog%io%action = 'IO'
       call setup%timing%io%get(prog%io%enabled)
       call prog%io%list(error)
       if (error) return
       prog%execution%action = 'EXECUTION'
       call setup%timing%command%get(prog%execution%enabled)
       call prog%execution%list(error)
       if (error) return       
    endif    
  end subroutine cubeset_timing_prog_act
end module cubeset_timing
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
