#ifndef BmlLalHodoscopeEventData_HH
#define BmlLalHodoscopeEventData_HH

#include <iostream>
#include <fstream>

#include "UtlPack.hh"


class BmlLalHodoscopeEventData {

public:
  enum {
    versionNumber=0
  };

  BmlLalHodoscopeEventData();

  unsigned numberOfWords() const;
  void     numberOfWords(unsigned d);

  unsigned status() const;
  void     status(unsigned d);

  bool empty() const;
  unsigned eventCounter() const;
  
  unsigned timeCounter() const;
  void     timeCounter(unsigned d);

  unsigned numberOfHits() const;

  bool hitX(unsigned n) const;
  unsigned short hitChannel(unsigned n) const;
  unsigned short hitValue(unsigned n) const;

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


private:
  unsigned _numberOfWords;
  UtlPack _status;
  unsigned _timeCounter;
};


#ifdef CALICE_DAQ_ICC

#include <time.h>
#include <cstring>

#include "UtlPrintHex.hh"


BmlLalHodoscopeEventData::BmlLalHodoscopeEventData() {
  memset(this,0,sizeof(BmlLalHodoscopeEventData));
}

unsigned BmlLalHodoscopeEventData::numberOfWords() const {
  return _numberOfWords;
}

void BmlLalHodoscopeEventData::numberOfWords(unsigned n) {
  _numberOfWords=n;
}

unsigned BmlLalHodoscopeEventData::status() const {
  return _status.word();
}

void BmlLalHodoscopeEventData::status(unsigned d) {
  _status.word(d);
}

bool BmlLalHodoscopeEventData::empty() const {
  return _status.bit(31);
}

unsigned BmlLalHodoscopeEventData::eventCounter() const {
  return _status.halfWord(0);
}

unsigned BmlLalHodoscopeEventData::timeCounter() const {
  return _timeCounter;
}

void BmlLalHodoscopeEventData::timeCounter(unsigned n) {
  _timeCounter=n;
}

unsigned BmlLalHodoscopeEventData::numberOfHits() const {
  if(_numberOfWords>2) return _numberOfWords-2;
  return 0;
}

bool BmlLalHodoscopeEventData::hitX(unsigned n) const {
  assert(n+2<_numberOfWords);
  const UtlPack *p((const UtlPack*)(this+1));
  return !p[n].bit(7);
}

unsigned short BmlLalHodoscopeEventData::hitChannel(unsigned n) const {
  assert(n+2<_numberOfWords);
  const UtlPack *p((const UtlPack*)(this+1));
  return p[n].bits(0,6);
}

unsigned short BmlLalHodoscopeEventData::hitValue(unsigned n) const {
  assert(n+2<_numberOfWords);
  const UtlPack *p((const UtlPack*)(this+1));
  return p[n].halfWord(1);
}

std::ostream& BmlLalHodoscopeEventData::print(std::ostream &o, std::string s) const {
  o << s << "BmlLalHodoscopeEventData::print()" << std::endl;
  o << s << " Number of words = " << _numberOfWords << std::endl;

  o << s << " Status = " << printHex(_status) << std::endl;
  o << s << "  Status value = " << _status.bits(28,31);
  if(empty()) o << ", empty";
  if(_status.bits(28,30)==1) o << ", general error";
  if(_status.bits(28,30)==2) o << ", bad board status";
  if(_status.bits(28,30)==3) o << ", trigger lost";
  if(_status.bits(28,30)==4) o << ", event lost";
  if(_status.bits(28,30)==5) o << ", no event";
  if(_status.bits(28,30)==6) o << ", unknown error";
  if(_status.bits(28,30)==7) o << ", unknown error";
  o << std::endl;

  o << s << "  Trgz counter = " << (unsigned)_status.byte(2) << std::endl;
  o << s << "  Event counter = " << eventCounter() << std::endl;

  o << s << " Time counter (x6.4us) = " << printHex(_timeCounter) << std::endl;

  o << s << " Number of hits = " << numberOfHits() << std::endl;

  const UtlPack *p((const UtlPack*)(this+1));
  for(unsigned i(0);i<numberOfHits();i++) {
    o << s << "  Hit " << std::setw(4) << i << " = "
      << printHex(p[i]) << std::endl;

    if(hitX(i)) o << s << "   X";
    else        o << s << "   Y";
    o << " channel = " << std::setw(5) << hitChannel(i)
      << ", value = " << std::setw(5) << hitValue(i);

    if(p[i].byte(1)!=0) o << ", ERROR spare bits = " << printHex(p[i].byte(3));
    o  << std::endl;
  }

  return o;
}

#endif
#endif
