#ifndef CrcLocation_HH
#define CrcLocation_HH

#include <string>
#include <iostream>

#include "UtlLocation.hh"

class CrcLocation : public UtlLocation {

public:
  enum CrcComponent {
    fe0,fe1,fe2,fe3,fe4,fe5,fe6,fe7,be,vme,beTrg,
    vmeLm82,vmeAdm1025,feBroadcast,
    endOfCrcComponentEnum
  };
    
  CrcLocation();
  CrcLocation(unsigned char c, unsigned char s, unsigned char f, unsigned char l=0);
  CrcLocation(unsigned char c, unsigned char s, CrcComponent f, unsigned char l=0);
  
  CrcComponent       crcComponent() const;
  void               crcComponent(CrcComponent f);
  std::string        crcComponentName() const;
  static std::string crcComponentName(CrcComponent c);

  bool verify() const;

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


private:
  static const std::string _crcComponentName[endOfCrcComponentEnum];
};


#ifdef CALICE_DAQ_ICC

#include "UtlPrintHex.hh"

CrcLocation::CrcLocation() : UtlLocation() {
}

CrcLocation::CrcLocation(unsigned char c, unsigned char s, unsigned char f, unsigned char l) : 
  UtlLocation(c,s,f,l) {
}
  
CrcLocation::CrcLocation(unsigned char c, unsigned char s, CrcComponent f, unsigned char l) :
  UtlLocation(c,s,f,l) {
}
  
CrcLocation::CrcComponent CrcLocation::crcComponent() const {
  return (CrcComponent)componentNumber();
}
  
void CrcLocation::crcComponent(CrcComponent f) {
  componentNumber((unsigned char)f);
}
  
std::string CrcLocation::crcComponentName() const {
  return crcComponentName(crcComponent());
}

std::string CrcLocation::crcComponentName(CrcComponent c) {
  if(c<endOfCrcComponentEnum) return _crcComponentName[c];
  return "Unknown";
}

bool CrcLocation::verify() const {
  return slotNumber()<22 &&
    crcComponent()<endOfCrcComponentEnum &&
    label()<8;
}

std::ostream& CrcLocation::print(std::ostream &o, std::string s) const {
  o << s << "CrcLocation::print()" << std::endl;

  o << s << " Crate number     = "
    << printHex(crateNumber(),false) << std::endl;

  o << s << " Slot number      = " << std::setw(4)
    << (unsigned)slotNumber();
  if(slotBroadcast()) o << " = Slot broadcast";
  else if(slotNumber()>21) o << " = Unphysical";
  o << std::endl;

  o << s << " CRC Component    = " << std::setw(4) << (unsigned)crcComponent() 
    << " = " << crcComponentName() << std::endl;

  o << s << " Label            = " << printHex(label());
  if(write()) o << " = write";
  else        o << " = read";
  if(ignore()) o << ", ignore";
  o << std::endl;

  return o;
}

const std::string CrcLocation::_crcComponentName[]={
  "FE0","FE1","FE2","FE3","FE4","FE5","FE6","FE7","BE","Vme","BE-Trg",
  "VmeLM82","VmeADM1025","FE Broadcast"
};

#endif
#endif
