#ifndef MpsSensor1Hit_HH
#define MpsSensor1Hit_HH

#include <iostream>
#include <fstream>

#include "UtlPack.hh"


class MpsSensor1Hit {

public:
  MpsSensor1Hit();
  MpsSensor1Hit(unsigned d);

  unsigned pixelX() const;
  void     pixelX(unsigned i);

  unsigned pixelY() const;
  void     pixelY(unsigned j);

  double localX() const;
  double localY() const;

  unsigned x() const;
  void     x(unsigned i);

  unsigned y() const;
  void     y(unsigned j);

  unsigned timeStamp() const;
  void     timeStamp(unsigned t);

  // Conversion from pixel number to space coordinate
  static double localX(unsigned x);
  static double localY(unsigned y);

  static unsigned pixelX(double x);
  static unsigned pixelY(double y);

  void datum(unsigned d);

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


private:
  UtlPack _datum;
};


#ifdef CALICE_DAQ_ICC

#include <cstring>

#include "UtlPrintHex.hh"


MpsSensor1Hit::MpsSensor1Hit() {
}

MpsSensor1Hit::MpsSensor1Hit(unsigned d) : _datum(d) {
}

unsigned MpsSensor1Hit::pixelX() const {
  return _datum.bits(0,8);
}

void MpsSensor1Hit::pixelX(unsigned i) {
  //assert(i<168);
  if(i>0xfffffff9) i-=0xfffffff9;
  if(i>=168) std::cerr << "MpsSensor1Hit::pixelX()  ERROR i = "
		       << i << " >= 168" << std::endl;
  _datum.bits(0,8,i);
}

unsigned MpsSensor1Hit::pixelY() const {
  return _datum.bits(9,17);
}

void MpsSensor1Hit::pixelY(unsigned j) {
  assert(j<168);
  _datum.bits(9,17,j);
}

double MpsSensor1Hit::localX() const {
  return localX(pixelX());
}

double MpsSensor1Hit::localY() const {
  return localY(pixelY());
}

unsigned MpsSensor1Hit::timeStamp() const {
  return _datum.bits(18,31);
}

void MpsSensor1Hit::timeStamp(unsigned t) {
  assert(t<(1<<14));
  _datum.bits(18,31,t);
}

void MpsSensor1Hit::datum(unsigned d) {
  _datum.word(d);
}

double MpsSensor1Hit::localX(unsigned x) {
  assert(x<168);

  if(x< 42) return -4.425+0.050*(x   );
  if(x< 84) return -4.425+0.050*(x+ 5);
  if(x<126) return -4.425+0.050*(x+10);
            return -4.425+0.050*(x+15);
}

double MpsSensor1Hit::localY(unsigned y) {
  assert(y<168);

  if(y<84) return 4.200-0.050*(y  );
  else     return 4.200-0.050*(y+1);
}

unsigned MpsSensor1Hit::pixelX(double x) {
  if(x>=-4.450 && x<-2.350) return (unsigned)((x+4.450)/0.05)   ;
  if(x>=-2.100 && x< 0.000) return (unsigned)((x+4.450)/0.05)- 5;
  if(x>= 0.250 && x< 2.350) return (unsigned)((x+4.450)/0.05)-10;
  if(x>= 2.600 && x< 4.700) return (unsigned)((x+4.450)/0.05)-15;
  return 0xffffffff;
}

unsigned MpsSensor1Hit::pixelY(double y) {
  if(y>= 0.025 && y< 4.225) return (unsigned)((4.225-y)/0.05)  ;
  if(y>=-4.225 && y<-0.025) return (unsigned)((4.225-y)/0.05)-1;
  return 0xffffffff;
}

std::ostream& MpsSensor1Hit::print(std::ostream &o, std::string s) const {
  o << s << "MpsSensor1Hit::print()" << std::endl;
  o << s << " Datum = " << printHex(_datum.word()) << std::endl;
  o << s << "  Pixel x = " << pixelX() << ", y = " << pixelY() << std::endl;
  o << s << "  Local x = " << localX() << ", y = " << localY() << std::endl;
  o << s << "  Timestamp = " << timeStamp() << std::endl;

  return o;
}

#endif
#endif
