#ifndef CrcVlinkHeader_HH
#define CrcVlinkHeader_HH

#include <string>
#include <iostream>

#include "UtlPack.hh"


class CrcVlinkHeader {

public:
  CrcVlinkHeader();

  unsigned char boe() const;
  unsigned char eventType() const;
  unsigned short eventNumber() const;
  unsigned short bunchCrossing() const;
  unsigned short sourceId() const;
  unsigned char formatVersion() const;

  bool lastHeader() const;
  unsigned char reserved() const;
  void data(unsigned m, unsigned l);

  bool verify() const;

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


private:
  UtlPack _data[2];
};

#ifdef CALICE_DAQ_ICC

CrcVlinkHeader::CrcVlinkHeader() {
}

unsigned char CrcVlinkHeader::boe() const {
  return _data[0].halfByte(7);
}

unsigned char CrcVlinkHeader::eventType() const {
  return _data[0].halfByte(6);
}

unsigned short CrcVlinkHeader::eventNumber() const {
  return _data[0].word()&0xffffff;
}

unsigned short CrcVlinkHeader::bunchCrossing() const {
  return _data[1].word()>>20;
}

unsigned short CrcVlinkHeader::sourceId() const {
  return (_data[1].word()>>8)&0xfff;
}

unsigned char CrcVlinkHeader::formatVersion() const {
  return _data[1].halfByte(1);
}

bool CrcVlinkHeader::lastHeader() const {
  return !_data[1].bit(3);
}

unsigned char CrcVlinkHeader::reserved() const {
  return _data[1].halfByte(0)&0x7;
}

void CrcVlinkHeader::data(unsigned m, unsigned l) {
  _data[0].word(m);
  _data[1].word(l);
}

bool CrcVlinkHeader::verify() const {
  return boe()==0x05 && eventType()==2 && sourceId()==0xcec &&
    formatVersion()==1 && !lastHeader() && reserved()==0;
}

std::ostream& CrcVlinkHeader::print(std::ostream &o, std::string s) const {
  o << s << "CrcVlinkHeader::print()" << std::endl;
  o << s << " MS bytes = " << printHex(_data[0].word()) << std::endl;
  o << s << "  BoE label      = " << printHex(boe()) << std::endl;
  o << s << "  Event type     = " << printHex(eventType()) << std::endl;
  o << s << "  Event number   = " << eventNumber() << std::endl;
  o << s << " LS bytes = " << printHex(_data[1].word()) << std::endl;
  o << s << "  Bunch crossing = " << bunchCrossing() << std::endl;
  o << s << "  Source id      = " << printHex(sourceId()) << std::endl;
  o << s << "  Format version = " << printHex(formatVersion()) << std::endl;
  if(lastHeader()) o << s << "  Last header" << std::endl;
  else             o << s << "  Following header" << std::endl;
  o << s << "  Reserved bits  = " << printHex(reserved()) << std::endl;

  return o;
}

#endif
#endif
