module cubeio_timing
  use gkernel_types
  use gkernel_interfaces
  use cubetools_format
  use cubeio_messaging

  type cubeio_time_t
    type(cputime_t) :: total  ! Total execution time
    type(cputime_t) :: read   ! Reading data from disk
    type(cputime_t) :: writ   ! Writing data to disk
  contains
    procedure :: init     => cubeio_timing_init
    procedure :: feedback => cubeio_timing_feedback
  end type cubeio_time_t

  public :: cubeio_time_t
  public :: gag_cputime_add
  private

contains

  subroutine cubeio_timing_init(time,error)
    !---------------------------------------------------------------------
    !---------------------------------------------------------------------
    class(cubeio_time_t), intent(inout) :: time
    logical,              intent(inout) :: error
    !
    call gag_cputime_init(time%total)
    call gag_cputime_init(time%read)
    call gag_cputime_init(time%writ)
  end subroutine cubeio_timing_init

  subroutine cubeio_timing_feedback(time,siz)
    !---------------------------------------------------------------------
    !---------------------------------------------------------------------
    class(cubeio_time_t), intent(in) :: time
    integer(kind=data_k), intent(in) :: siz
    !
    character(len=*), parameter :: rname='TIMING>FEEDBACK'
    character(len=mess_l) :: mess
    !
    print *,''
    !
  !!$ *** JP filename is not there anymore...
  !!$  write(mess,'(A,T45,A)')  trim(cub%head%gen%filename),cubetools_format_memsize(siz)
    write(mess,'(T45,A)') cubetools_format_memsize(siz)
    call cubeio_message(seve%r,rname,mess)
    !
    call print_it('Lifetime:',                     time%total%diff%elapsed,siz,.false.)
    call print_it('Time elapsed reading the cube:',time%read%curr%elapsed, siz,.true.)
    call print_it('Time elapsed writing the cube:',time%writ%curr%elapsed, siz,.true.)
    !
  end subroutine cubeio_timing_feedback

  subroutine print_it(prefix,elapsed,siz,dorate)
    character(len=*),     intent(in) :: prefix
    real(kind=8),         intent(in) :: elapsed
    integer(kind=data_k), intent(in) :: siz
    logical,              intent(in) :: dorate
    ! Local
    character(len=*), parameter :: rname='TIMING>FEEDBACK'
    character(len=mess_l) :: mess
    integer(kind=data_k) :: rate
    character(len=64) :: ratestr
    !
    if (dorate) then
      if (elapsed.le.0.d0) then
        rate = 0.d0
      else
        rate = siz/elapsed
      endif
      write(ratestr,'(3A)')  '(',trim(cubetools_format_memsize(rate)),'/sec)'
    else
      ratestr = ''
    endif
    write(mess,10)  prefix,elapsed,' sec ',ratestr
    call cubeio_message(seve%r,rname,mess)
    !
10  format(A,T40,F10.2,A,A)
  end subroutine print_it

  subroutine gag_cputime_add(sum,last)
    !---------------------------------------------------------------------
    !   Get the times since last call for 'last', and add the times to
    ! the structure 'sum'. Note that the reference times in 'sum' have
    ! not much meaning in this context.
    ! ---
    !   This subroutine is helpful to add non-contiguous time counts,
    ! while the official cputime_t is made to count times from a reference
    ! or from last call. Should this be merged in gsys?
    !---------------------------------------------------------------------
    type(cputime_t), intent(inout) :: sum
    type(cputime_t), intent(inout) :: last
    !
    call gag_cputime_get(last)
    sum%curr%elapsed = sum%curr%elapsed + last%diff%elapsed
    sum%curr%user    = sum%curr%user    + last%diff%user
    sum%curr%system  = sum%curr%system  + last%diff%system
  end subroutine gag_cputime_add

end module cubeio_timing
