#ifndef DaqMultiTimer_HH
#define DaqMultiTimer_HH

#include <string>
#include <iostream>
#include <iomanip>

#include "UtlTime.hh"


class DaqMultiTimer {

public:
  enum {
    versionNumber=0
  };

  enum {
    maxFifoLength=512,
    maxWordLength=maxFifoLength+8
  };

  DaqMultiTimer(bool u=true);

  unsigned timerId() const;
  void     timerId(unsigned n);

  unsigned numberOfTimers() const;

  void addTimer(bool u=true);
  /*
  const UtlTime* time() const;
  UtlTime*       time();
  */
  UtlTimeDifference timeDifference(unsigned i) const;

  unsigned bytesExtended() const;

  std::ostream& print(std::ostream &o, std::string s="") const;


private:
  unsigned _timerId;
  unsigned _numberOfExtraTimers;
  UtlTime _time[1];
};


#ifdef CALICE_DAQ_ICC

#include <cstring>

DaqMultiTimer::DaqMultiTimer(bool u) {
  memset(this,0,sizeof(DaqMultiTimer));
  if(u) _time[0].update();
}

unsigned DaqMultiTimer::timerId() const {
  return _timerId;
}

void DaqMultiTimer::timerId(unsigned n) {
  _timerId=n;
}

unsigned DaqMultiTimer::numberOfTimers() const {
  return _numberOfExtraTimers+1;
}

void DaqMultiTimer::addTimer(bool u) {
  _numberOfExtraTimers++;
  new(_time+_numberOfExtraTimers) UtlTime(u);
}

unsigned DaqMultiTimer::bytesExtended() const {
  return _numberOfExtraTimers*sizeof(UtlTime);
}

UtlTimeDifference DaqMultiTimer::timeDifference(unsigned i=0) const {
  assert(i<=_numberOfExtraTimers);
  if(i==0) return _time[_numberOfExtraTimers]-_time[0];
  else     return _time[i]-_time[i-1];
}

/*
const unsigned* DaqMultiTimer::fifoData() const {
  return &_numberOfFifoWords+1;
}

unsigned* DaqMultiTimer::fifoData() {
  return &_numberOfFifoWords+1;
}
*/

std::ostream& DaqMultiTimer::print(std::ostream &o, std::string s) const {
  o << s << "DaqMultiTimer::print()" << std::endl;
  o << s << " Timer Id  = " << printHex(_timerId) << std::endl;
  o << s << " Number of timers = " << std::setw(10) << numberOfTimers() << std::endl;

  o << s << "  Time  0 = " << _time[0]
    << ", total diff = " << timeDifference(0) << std::endl;
  for(unsigned i(1);i<numberOfTimers();i++) {
    o << s << "  Time " << std::setw(2) << i << " = " 
      << _time[i] << ", difference = " << timeDifference(i) << std::endl;
  }
  
  return o;
}

#endif
#endif
