#ifndef UtlLocation_HH
#define UtlLocation_HH

#include <string>
#include <iostream>

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


class UtlLocation {

public:
  UtlLocation();  
  UtlLocation(unsigned char c, unsigned char s, unsigned char f);  
  UtlLocation(unsigned char c, unsigned char s, unsigned char f, unsigned char l);
  
  unsigned char crateNumber() const;  
  void          crateNumber(unsigned char n);
  
  unsigned char slotNumber() const;
  void          slotNumber(unsigned char n);
  bool          slotBroadcast() const;  
  void          slotBroadcast(bool e);
  
  unsigned char componentNumber() const;  
  void          componentNumber(unsigned char n);
  
  unsigned char label() const;
  void          label(unsigned char n);

  bool          write() const;
  void          write(bool w);

  bool          ignore() const;

  bool operator==(const UtlLocation &d) const;
  bool operator!=(const UtlLocation &d) const;
  
  std::ostream& print(std::ostream &o=std::cout, std::string s="") const;


private:
  UtlPack _location;
};


#ifdef CALICE_DAQ_ICC

UtlLocation::UtlLocation() : _location(0) {
}

UtlLocation::UtlLocation(unsigned char c, unsigned char s, unsigned char f) : _location(0) {
  crateNumber(c);
  slotNumber(s);
  componentNumber(f);
}
  
UtlLocation::UtlLocation(unsigned char c, unsigned char s, unsigned char f, unsigned char l) {
  crateNumber(c);
  slotNumber(s);
  componentNumber(f);
  label(l);
}
  
unsigned char UtlLocation::crateNumber() const {
  return _location.byte(3);
}

void UtlLocation::crateNumber(unsigned char n) {
  _location.byte(3,n);
}

unsigned char UtlLocation::slotNumber() const {
  return _location.byte(2);
}

void UtlLocation::slotNumber(unsigned char n) {
  _location.byte(2,n);
}

bool UtlLocation::slotBroadcast() const {
  return _location.byte(2)==0xff;
}

void UtlLocation::slotBroadcast(bool e) {
  if(e) _location.byte(2,0xff);
  else  _location.byte(2,0x00);
}

unsigned char UtlLocation::componentNumber() const {
  return _location.byte(1);
}

void UtlLocation::componentNumber(unsigned char n) {
  _location.byte(1,n);
}

unsigned char UtlLocation::label() const {
  return _location.byte(0);
}

void UtlLocation::label(unsigned char n) {
  _location.byte(0,n);
}

bool UtlLocation::write() const {
  return _location.bit(0);
}

void UtlLocation::write(bool w) {
  _location.bit(0,w);
}

bool UtlLocation::ignore() const {
  return _location.bit(2);
}

bool UtlLocation::operator==(const UtlLocation &d) const {
  return _location==d._location;
}

bool UtlLocation::operator!=(const UtlLocation &d) const {
  return _location!=d._location;
}

std::ostream& UtlLocation::print(std::ostream &o, std::string s) const {
  o << s << "UtlLocation::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";
  o << std::endl;

  o << s << " Component number = " << std::setw(4)
    << (unsigned)componentNumber() << std::endl;

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

  return o;
}

#endif

#endif
