#ifndef MpsLaserConfigurationData_HH
#define MpsLaserConfigurationData_HH

#include <iostream>
#include <fstream>

#include "UtlPack.hh"


class MpsLaserConfigurationData {

public:
  enum {
    versionNumber=0
  };

  MpsLaserConfigurationData();

  unsigned messageId() const;
  void     messageId(unsigned s);

  bool write() const;

  unsigned intensity() const;
  void     intensity(unsigned i);

  unsigned timeout() const;
  void     timeout(unsigned i);

  int  stageX() const;
  void stageX(int i);

  int  stageY() const;
  void stageY(int j);

  unsigned triggerMode() const;
  void     triggerMode(unsigned c);

  unsigned status() const;
  void     status(unsigned c);

  unsigned fireMode() const;
  void     fireMode(unsigned c);

  unsigned repetitionRate() const;
  void     repetitionRate(unsigned p);

  unsigned numberOfPulses() const;
  void     numberOfPulses(unsigned p);

  bool        parse(const std::string &r);
  std::string parse() const;

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


private:
  unsigned _messageId;
  unsigned _intensity;
  int      _stageX;
  int      _stageY;
  unsigned _triggerMode;
  unsigned _fireMode;
  unsigned _repetitionRate;
  unsigned _numberOfPulses;
};


#ifdef CALICE_DAQ_ICC

#include <cstring>

#include "UtlPrintHex.hh"


MpsLaserConfigurationData::MpsLaserConfigurationData() {
  memset(this,0,sizeof(MpsLaserConfigurationData));

  // Label as write configuration by default
  _messageId=1;
}

unsigned MpsLaserConfigurationData::messageId() const {
  return _messageId;
}

void MpsLaserConfigurationData::messageId(unsigned s) {
  _messageId=s;
}

bool MpsLaserConfigurationData::write() const {
  return _messageId!=2;
}

unsigned MpsLaserConfigurationData::intensity() const {
  return _intensity;
}

void MpsLaserConfigurationData::intensity(unsigned c) {
  _intensity=c;
}

unsigned MpsLaserConfigurationData::timeout() const {
  return _intensity;
}

void MpsLaserConfigurationData::timeout(unsigned c) {
  _intensity=c;
}

int MpsLaserConfigurationData::stageX() const {
  return _stageX;
}

void MpsLaserConfigurationData::stageX(int i) {
  _stageX=i;
}

int MpsLaserConfigurationData::stageY() const {
  return _stageY;
}

void MpsLaserConfigurationData::stageY(int j) {
  _stageY=j;
}
 
unsigned MpsLaserConfigurationData::triggerMode() const {
  return _triggerMode;
}

void MpsLaserConfigurationData::triggerMode(unsigned c) {
  _triggerMode=c;
}

unsigned MpsLaserConfigurationData::status() const {
  return _triggerMode;
}

void MpsLaserConfigurationData::status(unsigned c) {
  _triggerMode=c;
}

unsigned MpsLaserConfigurationData::fireMode() const {
  return _fireMode;
}

void MpsLaserConfigurationData::fireMode(unsigned c) {
  _fireMode=c;
}

unsigned MpsLaserConfigurationData::repetitionRate() const {
  return _repetitionRate;
}

void MpsLaserConfigurationData::repetitionRate(unsigned c) {
  _repetitionRate=c;
}

unsigned MpsLaserConfigurationData::numberOfPulses() const {
  return _numberOfPulses;
}

void MpsLaserConfigurationData::numberOfPulses(unsigned c) {
  _numberOfPulses=c;
}

std::string MpsLaserConfigurationData::parse() const {
  std::ostringstream sout;

  assert(_messageId<10);
  sout << _messageId;

  assert(_intensity<1000);
  sout << std::setfill('0') << std::setw(3) << _intensity;

  assert(_stageX<100000);
  sout << std::setfill('0') << std::setw(5) << _stageX;

  assert(_stageY<100000);
  sout << std::setfill('0') << std::setw(5) << _stageY;

  assert(_triggerMode<10);
  sout << _triggerMode;

  assert(_fireMode<10);
  sout << _fireMode;

  assert(_repetitionRate<100);
  sout << std::setfill('0') << std::setw(2) << _repetitionRate;

  assert(_numberOfPulses<1000);
  sout << std::setfill('0') << std::setw(3) << _numberOfPulses;

  //       234567890123456
  sout << "!LOTSOFPADDING!";

  return sout.str();
}
 
bool MpsLaserConfigurationData::parse(const std::string &r) {

  // Check packet is for run data
  if(r.size()<21) return false;
  //if(r[0]!='2') return false;
 
  // Get message ID
  {char c[2];
  c[0]=r[0];
  c[1]='\0';
 
  std::istringstream sin(c);
  sin >> _messageId;
  if(!sin) return false;}
 
  // Get intensity, etc
  unsigned digit;
 
  _intensity=0;
  for(unsigned i(0);i<3;i++) {
    _intensity*=10;
 
    char c[2];
    c[0]=r[i+1];
    c[1]='\0';
 
    std::istringstream sin(c);
    sin >> digit;
    if(!sin) return false;
 
    _intensity+=digit;
  }

  _stageX=0;
  for(unsigned i(0);i<5;i++) {
    _stageX*=10;
 
    char c[2];
    c[0]=r[i+4];
    c[1]='\0';
 
    std::istringstream sin(c);
    sin >> digit;
    if(!sin) return false;
 
    _stageX+=digit;
  }

  _stageY=0;
  for(unsigned i(0);i<5;i++) {
    _stageY*=10;
 
    char c[2];
    c[0]=r[i+9];
    c[1]='\0';
 
    std::istringstream sin(c);
    sin >> digit;
    if(!sin) return false;
 
    _stageY+=digit;
  }

  {char c[2];
  c[0]=r[14];
  c[1]='\0';
  
  std::istringstream sin(c);
  sin >> _triggerMode;
  if(!sin) return false;}

  {char c[2];
  c[0]=r[15];
  c[1]='\0';
  
  std::istringstream sin(c);
  sin >> _fireMode;
  if(!sin) return false;}
 
  _repetitionRate=0;
  for(unsigned i(0);i<2;i++) {
    _repetitionRate*=10;
 
    char c[2];
    c[0]=r[i+16];
    c[1]='\0';
 
    std::istringstream sin(c);
    sin >> digit;
    if(!sin) return false;
 
    _repetitionRate+=digit;
  }

  _numberOfPulses=0;
  for(unsigned i(0);i<3;i++) {
    _numberOfPulses*=10;
 
    char c[2];
    c[0]=r[i+18];
    c[1]='\0';
 
    std::istringstream sin(c);
    sin >> digit;
    if(!sin) return false;
 
    _numberOfPulses+=digit;
  }

  return true;
}

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

  o << s << " Message ID                  = " << _messageId;
  if(write()) o << " = write";
  o << std::endl;

  o << s << " Intensity/timeout           = " << _intensity << std::endl;
  o << s << " Stage x = " << stageX()
    << ", y = " << stageY() << std::endl;
  o << s << " Trigger mode/status         = " << printHex(_triggerMode) <<std::endl;
  o << s << " Fire mode                   = " << _fireMode <<std::endl;
  o << s << " Repetition rate             = " << _repetitionRate <<std::endl;
  o << s << " Number of pulses            = " << _numberOfPulses <<std::endl;

  return o;
}

#endif
#endif
