#ifndef RcdHeader_HH
#define RcdHeader_HH

#include <string>
#include <iostream>

// records/inc/utl
#include "UtlTime.hh"


class RcdHeader {

public:
  enum RecordType {
    startUp,
    runStart,
    configurationStart,
    acquisitionStart,   oldSpillStart=acquisitionStart,
    trigger,            preEvent=trigger,
    event,
    acquisitionStop,    oldSpillStop =acquisitionStop,
    acquisitionEnd,     oldSpillEnd  =acquisitionEnd,
    spillStart,
    spillEnd,
    configurationStop,
    configurationEnd,
    runStop,
    runEnd,
    fileContinuation,
    sequenceStart,      oldSlowStart        =sequenceStart,
    sequenceEnd,        oldSlowConfiguration=sequenceEnd,
    slowReadout,
    slowEnd,   // Unused
    shutDown,
    postEvent, // Unused
    spill,
    triggerBurst,       oldTransfer=triggerBurst,
    transferStart,
    transferEnd,
    bunchTrain,
    doNothing,
    endOfRecordTypeEnum
  };


  RcdHeader();

  UtlTime recordTime() const;
  void recordTime(const UtlTime &t);
  void updateRecordTime();

  RecordType recordType() const;
  void recordType(RecordType t);
  std::string recordTypeName() const;
  static std::string recordTypeName(RecordType t);

  void initialise(RecordType t);

  bool operator!=(const RcdHeader& that) const;
  bool operator==(const RcdHeader& that) const;

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


protected:
  static const std::string _recordTypeName[endOfRecordTypeEnum];

  UtlTime  _recordTime;
  RecordType _recordType;
};


#ifdef CALICE_DAQ_ICC

#include <assert.h>
#include <iomanip>


RcdHeader::RcdHeader() : _recordTime(), _recordType(startUp) {
}

UtlTime RcdHeader::recordTime() const {
  return _recordTime;
}

void RcdHeader::recordTime(const UtlTime &t) {
  _recordTime=t;
}

void RcdHeader::updateRecordTime() {
  _recordTime.update();
}

RcdHeader::RecordType RcdHeader::recordType() const {
  return _recordType;
}

void RcdHeader::recordType(RecordType t) {
  _recordType=t;
}

std::string RcdHeader::recordTypeName() const {
  return recordTypeName(_recordType);
}

std::string RcdHeader::recordTypeName(RecordType t) {
  assert(t<endOfRecordTypeEnum);
  return _recordTypeName[t];
}

void RcdHeader::initialise(RecordType t) {
  _recordTime.update();
  _recordType=t;  
}

bool RcdHeader::operator==(const RcdHeader& that) const {
  if(_recordTime  !=that._recordTime  ) return false;
  if(_recordType  !=that._recordType  ) return false;
  return true;
}

bool RcdHeader::operator!=(const RcdHeader& that) const {
  return !((*this)==that);
}

std::ostream& RcdHeader::print(std::ostream &o, std::string s) const {
  o << s << "RcdHeader::print()  Record Time = " << _recordTime
    << ",  Type = " << std::setw(2) << _recordType << " = " 
    << recordTypeName() << std::endl;
    return o;
}


const std::string RcdHeader::_recordTypeName[]={
    "startUp           ",
    "runStart          ",
    "configurationStart",
    "acquisitionStart  ",
    "trigger           ",
    "event             ",
    "acquisitionStop   ",
    "acquisitionEnd    ",
    "spillStart        ",
    "spillEnd          ",
    "configurationStop ",
    "configurationEnd  ",
    "runStop           ",
    "runEnd            ",
    "fileEnd           ",
    "sequenceStart     ",
    "sequenceEnd       ",
    "slowReadout       ",
    "slowEnd           ",
    "shutDown          ",
    "postEvent         ",
    "spill             ",
    "triggerBurst      ",
    "transferStart     ",
    "transferEnd       ",
    "bunchTrain        ",
    "doNothing         "
};

#endif
#endif
