#ifndef DaqBurstEnd_HH
#define DaqBurstEnd_HH

#include <string>
#include <iostream>


class DaqBurstEnd {

public:
  enum {
    versionNumber=0
  };

  DaqBurstEnd();
  
  void reset();

  unsigned burstNumberInRun() const;
  void     burstNumberInRun(unsigned n);

  unsigned burstNumberInConfiguration() const;
  void     burstNumberInConfiguration(unsigned n);

  unsigned burstNumberInAcquisition() const;
  void     burstNumberInAcquisition(unsigned n);

  unsigned lastTriggerNumberInRun() const;
  void     lastTriggerNumberInRun(unsigned n);

  unsigned lastTriggerNumberInConfiguration() const;
  void     lastTriggerNumberInConfiguration(unsigned n);
  
  unsigned lastTriggerNumberInAcquisition() const;
  void     lastTriggerNumberInAcquisition(unsigned n);
  
  unsigned actualNumberOfExtraTriggersInBurst() const;
  void     actualNumberOfExtraTriggersInBurst(unsigned n);
  unsigned actualNumberOfTriggersInBurst() const;

  UtlTimeDifference actualTimeOfBurst() const;
  void              actualTimeOfBurst(UtlTimeDifference n);

  bool bufferFull() const;

  bool crcBufferFull() const;
  void crcBufferFull(bool b);

  bool tdcBufferFull() const;
  void tdcBufferFull(bool b);

  bool inSpill() const;
  void inSpill(bool b);

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


private:
  unsigned _burstNumberInRun;
  unsigned _burstNumberInConfiguration;
  unsigned _burstNumberInAcquisition;
  unsigned _lastTriggerNumberInRun;
  unsigned _lastTriggerNumberInConfiguration;
  unsigned _lastTriggerNumberInAcquisition;
  unsigned _actualNumberOfExtraTriggersInBurst;
  UtlTimeDifference _actualTimeOfBurst;
  UtlPack _flags;
};


#ifdef CALICE_DAQ_ICC

DaqBurstEnd::DaqBurstEnd() {
  reset();
}

void DaqBurstEnd::reset() {
  _burstNumberInRun=0;
  _burstNumberInConfiguration=0;
  _burstNumberInAcquisition=0;
  _lastTriggerNumberInRun=0;
  _lastTriggerNumberInConfiguration=0;
  _lastTriggerNumberInAcquisition=0;
  _actualNumberOfExtraTriggersInBurst=0;
  _actualTimeOfBurst=UtlTimeDifference(0x7fffffff,999999);
  _flags=0;
}

unsigned DaqBurstEnd::burstNumberInRun() const {
  return _burstNumberInRun;
}

void DaqBurstEnd::burstNumberInRun(unsigned n) {
  _burstNumberInRun=n;
}

unsigned DaqBurstEnd::burstNumberInConfiguration() const {
  return _burstNumberInConfiguration;
}

void DaqBurstEnd::burstNumberInConfiguration(unsigned n) {
  _burstNumberInConfiguration=n;
}

unsigned DaqBurstEnd::burstNumberInAcquisition() const {
  return _burstNumberInAcquisition;
}

void DaqBurstEnd::burstNumberInAcquisition(unsigned n) {
  _burstNumberInAcquisition=n;
}

unsigned DaqBurstEnd::lastTriggerNumberInRun() const {
  return _lastTriggerNumberInRun;
}

void DaqBurstEnd::lastTriggerNumberInRun(unsigned n) {
  _lastTriggerNumberInRun=n;
}

unsigned DaqBurstEnd::lastTriggerNumberInConfiguration() const {
  return _lastTriggerNumberInConfiguration;
}

void DaqBurstEnd::lastTriggerNumberInConfiguration(unsigned n) {
  _lastTriggerNumberInConfiguration=n;
}

unsigned DaqBurstEnd::lastTriggerNumberInAcquisition() const {
  return _lastTriggerNumberInAcquisition;
}

void DaqBurstEnd::lastTriggerNumberInAcquisition(unsigned n) {
  _lastTriggerNumberInAcquisition=n;
}

unsigned DaqBurstEnd::actualNumberOfExtraTriggersInBurst() const {
  return _actualNumberOfExtraTriggersInBurst;
}

void DaqBurstEnd::actualNumberOfExtraTriggersInBurst(unsigned n) {
  _actualNumberOfExtraTriggersInBurst=n;
}

unsigned DaqBurstEnd::actualNumberOfTriggersInBurst() const {
  return _actualNumberOfExtraTriggersInBurst+1;
}

UtlTimeDifference DaqBurstEnd::actualTimeOfBurst() const {
  return _actualTimeOfBurst;
}
 
void DaqBurstEnd::actualTimeOfBurst(UtlTimeDifference m) {
  _actualTimeOfBurst=m;
}

bool DaqBurstEnd::bufferFull() const {
  return _flags.bit(0) || _flags.bit(2);
}

bool DaqBurstEnd::crcBufferFull() const {
  return _flags.bit(0);
}

void DaqBurstEnd::crcBufferFull(bool b) {
  _flags.bit(0,b);
}

bool DaqBurstEnd::inSpill() const {
  return _flags.bit(1);
}

void DaqBurstEnd::inSpill(bool b) {
  _flags.bit(1,b);
}

bool DaqBurstEnd::tdcBufferFull() const {
  return _flags.bit(2);
}

void DaqBurstEnd::tdcBufferFull(bool b) {
  _flags.bit(2,b);
}

std::ostream& DaqBurstEnd::print(std::ostream &o, std::string s) const {
  o << s << "DaqBurstEnd::print() Burst numbers in run "
    << _burstNumberInRun << ", in configuration "
    << _burstNumberInConfiguration << ", in acquisition "
    << _burstNumberInAcquisition << std::endl;

  o << s << " Last trigger numbers in run "
    << _lastTriggerNumberInRun << ", in configuration "
    << _lastTriggerNumberInConfiguration << ", in acquisition "
    << _lastTriggerNumberInAcquisition << std::endl;

  o << s << " Actual number of extra triggers in burst " << 
    _actualNumberOfExtraTriggersInBurst << std::endl;
  o << s << " Actual time of burst "
    << _actualTimeOfBurst.deltaTime() << " secs" << std::endl;

  o << s << " Flags: ";
  if(bufferFull()) o << " At least one buffer full";
  else             o << " All buffers not full";
  if(crcBufferFull()) o << ", CRC buffers full";
  else                o << ", CRC buffers not full";
  if(tdcBufferFull()) o << ", TDC buffers full";
  else                o << ", TDC buffers not full";
  if(inSpill())    o << ", In spill";
  else             o << ", Out of spill";
  o << std::endl;

  return o;
}

#endif
#endif
