#ifndef BmlSlowRunData_HH
#define BmlSlowRunData_HH

#include <string>
#include <iostream>

#include "UtlPack.hh"


class BmlSlowRunData {

public:
  enum {
    versionNumber=0
  };

  BmlSlowRunData();

  bool parse(std::string r);
  bool parse(std::string r, unsigned p);
  
  time_t timeStamp() const;
  void   timeStamp(time_t t);

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


private:
  time_t _timeStamp;

  double _sextapoleCurrent[2][2];
  double _absorberPosition;
  double _bendCurrent[9][2];
  double _collimatorPosition[11][2][2];
  unsigned _h6aExperimentCount[4];
  unsigned _h6bExperimentCount[4];
  unsigned _h6cExperimentCount[4];
  double _quadrupoleCurrent[16][2];
  unsigned _rpExperimentCount[8];
  unsigned _scintillatorCount[9];
  double _t4Position;
  double _targetPosition;
  double _trimCurrent[6][2];
};


#ifdef CALICE_DAQ_ICC

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


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

bool BmlSlowRunData::parse(std::string r) {
  std::istringstream sin(r);
  sin >> _timeStamp;
  if(!sin) return false;

  for(unsigned i(0);i<2 && sin;i++) {
    for(unsigned j(0);j<2 && sin;j++) {
      sin >> _sextapoleCurrent[i][j];
      if(!sin) return false;
    }
  }

  sin >> _absorberPosition;
  if(!sin) return false;

  for(unsigned i(0);i<9 && sin;i++) {
    if(i!=7) { // BEND08 missing?
      for(unsigned j(0);j<2 && sin;j++) {
	sin >> _bendCurrent[i][j];
	if(!sin) return false;
      }
    }
  }

  for(unsigned i(0);i<11 && sin;i++) {
    if(i!=3 && i!=6) { // COLL04 and COLL07 missing?
      for(unsigned j(0);j<2 && sin;j++) {
	for(unsigned k(0);k<2 && sin;k++) {
	  sin >> _collimatorPosition[i][j][k];
	  if(!sin) return false;
	}
      }
    }
  }
  
  for(unsigned i(0);i<4 && sin;i++) {
    sin >> _h6aExperimentCount[i];
    if(!sin) return false;
  }
  
  for(unsigned i(0);i<4 && sin;i++) {
    sin >> _h6bExperimentCount[i];
    if(!sin) return false;
  }
  
  for(unsigned i(0);i<4 && sin;i++) {
    sin >> _h6cExperimentCount[i];
    if(!sin) return false;
  }
  
  for(unsigned i(0);i<16 && sin;i++) {
    for(unsigned j(0);j<2 && sin;j++) {
      sin >> _quadrupoleCurrent[i][j];
      if(!sin) return false;
    }
  }

  for(unsigned i(0);i<8 && sin;i++) {
    sin >> _rpExperimentCount[i];
    if(!sin) return false;
  }

  for(unsigned i(0);i<9 && sin;i++) {
    if(i!=1 && i!=2) { // SCINT02 and SCINT03 missing?
      sin >> _scintillatorCount[i];
      if(!sin) return false;
    }
  }

  sin >> _t4Position;
  if(!sin) return false;

  sin >> _targetPosition;
  if(!sin) return false;
  
  for(unsigned i(0);i<6 && sin;i++) {
    for(unsigned j(0);j<2 && sin;j++) {
      sin >> _trimCurrent[i][j];
      if(!sin) return false;
    }
  }
  
  return sin;
}

bool BmlSlowRunData::parse(std::string r, unsigned p) {
  assert(p<=10);

  std::istringstream sin(r);

  // Choose to stroe timestamp here only  
  if(p==0) {
    sin >> _timeStamp;
    if(!sin) return false;

    for(unsigned i(0);i<2 && sin;i++) {
      for(unsigned j(0);j<2 && sin;j++) {
	sin >> _sextapoleCurrent[i][j];
	if(!sin) return false;
      }
    }
    return sin;
  }

  if(p==1) {
    unsigned ts;
    sin >> ts;
    if(!sin) return false;

    sin >> _absorberPosition;
    if(!sin) return false;
    return sin;
  }

  if(p==2) {
    unsigned ts;
    sin >> ts;
    if(!sin) return false;
    
    for(unsigned i(0);i<9 && sin;i++) {
      if(i!=7) { // BEND08 missing?
	for(unsigned j(0);j<2 && sin;j++) {
	  sin >> _bendCurrent[i][j];
	  if(!sin) return false;
	}
      }
    }
    return sin;
  }
  
  if(p==3) {
    unsigned ts;
    sin >> ts;
    if(!sin) return false;
    
    for(unsigned i(0);i<11 && sin;i++) {
      if(i!=3 && i!=6) { // COLL04 and COLL07 missing?
	for(unsigned j(0);j<2 && sin;j++) {
	  for(unsigned k(0);k<2 && sin;k++) {
	    sin >> _collimatorPosition[i][j][k];
	    if(!sin) return false;
	  }
	}
      }
    }
    return sin;
  }  
  
  if(p==4) {
    unsigned ts;
    sin >> ts;
    if(!sin) return false;

    double ec;    
    for(unsigned i(0);i<4 && sin;i++) {
      sin >> ec;
      _h6aExperimentCount[i]=(unsigned)(ec+0.5);
      if(!sin) return false;
    }
    
    for(unsigned i(0);i<4 && sin;i++) {
      sin >> ec;
      _h6bExperimentCount[i]=(unsigned)(ec+0.5);
      if(!sin) return false;
    }
    
    for(unsigned i(0);i<4 && sin;i++) {
      sin >> ec;
      _h6cExperimentCount[i]=(unsigned)(ec+0.5);
      if(!sin) return false;
    }
    return sin;
  }
  
  if(p==5) {
    unsigned ts;
    sin >> ts;
    if(!sin) return false;
    
    for(unsigned i(0);i<16 && sin;i++) {
      for(unsigned j(0);j<2 && sin;j++) {
	sin >> _quadrupoleCurrent[i][j];
	if(!sin) return false;
      }
    }
    return sin;
  }
  
  if(p==6) {
    unsigned ts;
    sin >> ts;
    if(!sin) return false;

    double ec;
    for(unsigned i(0);i<8 && sin;i++) {
      sin >> ec;
      _rpExperimentCount[i]=(unsigned)(ec+0.5);
      if(!sin) return false;
    }
    return sin;
  }
  
  if(p==7) {
    unsigned ts;
    sin >> ts;
    if(!sin) return false;
    
    double sc;
    for(unsigned i(0);i<9 && sin;i++) {
      if(i!=1 && i!=2) { // SCINT02 and SCINT03 missing?
	sin >> sc;
	_scintillatorCount[i]=(unsigned)(sc+0.5);
	if(!sin) return false;
      }
    }
    return sin;
  }
  
  if(p==8) {
    unsigned ts;
    sin >> ts;
    if(!sin) return false;
    
    sin >> _t4Position;
    if(!sin) return false;
    return sin;
  }
  
  if(p==9) {
    unsigned ts;
    sin >> ts;
    if(!sin) return false;
    
    sin >> _targetPosition;
    if(!sin) return false;
    return sin;
  }
    
  if(p==10) {
    unsigned ts;
    sin >> ts;
    if(!sin) return false;
    
    for(unsigned i(0);i<6 && sin;i++) {
      for(unsigned j(0);j<2 && sin;j++) {
	sin >> _trimCurrent[i][j];
	if(!sin) return false;
      }
    }
    return sin;
  }
  
  return sin;
}

time_t BmlSlowRunData::timeStamp() const {
  return _timeStamp;
}

void BmlSlowRunData::timeStamp(time_t t) {
  _timeStamp=t;
}

std::ostream& BmlSlowRunData::print(std::ostream &o, std::string s) const {
  o << s << "BmlSlowRunData::print()" << std::endl;
  o << s << " Timestamp = " << _timeStamp << " = " << ctime(&_timeStamp);

  for(unsigned i(0);i<2;i++) {
    for(unsigned j(0);j<2;j++) {
      o << s << " Sextapole current " << i;
      if(j==0) o << " measured  = ";
      else     o << " reference = ";
      o << _sextapoleCurrent[i][j] << " A" << std::endl;
    }
  }
  
  o << s << " Absorber position " << _absorberPosition << std::endl;

  for(unsigned i(0);i<9;i++) {
    for(unsigned j(0);j<2;j++) {
      o << s << " Bend current " << i;
      if(j==0) o << " measured  = ";
      else     o << " reference = ";
      o << _bendCurrent[i][j] << " A" << std::endl;
    }
  }
  
  for(unsigned i(0);i<11;i++) {
    for(unsigned j(0);j<2;j++) {
      for(unsigned k(0);k<2;k++) {
	o << s << " Collimator position " << _collimatorPosition[i][j][k] << std::endl;
      }
    }
  }
  
  for(unsigned i(0);i<4;i++) {
    o << s << " H6A experiment " << i << " count = "
      << _h6aExperimentCount[i] << std::endl;
  }
  
  for(unsigned i(0);i<4;i++) {
    o << s << " H6B experiment " << i << " count = "
      << _h6bExperimentCount[i] << std::endl;
  }
  
  for(unsigned i(0);i<4;i++) {
    o << s << " H6C experiment " << i << " count = "
      << _h6cExperimentCount[i] << std::endl;
  }
  
  for(unsigned i(0);i<16;i++) {
    for(unsigned j(0);j<2;j++) {
      o << s << " Quadrupole current " << std::setw(2) << i;
      if(j==0) o << " measured  = ";
      else     o << " reference = ";
      o << _quadrupoleCurrent[i][j] << " A" << std::endl;
    }
  }

  for(unsigned i(0);i<8;i++) {
    o << s << " RP experiment " << i << " count = "
      << _rpExperimentCount[i] << std::endl;
  }

  for(unsigned i(0);i<9;i++) {
    o << s << " Scintillator " << i << " count = "
      << _scintillatorCount[i] << std::endl;
  }

  o << s << " T4 position " << _t4Position << std::endl;

  o << s << " Target position " << _targetPosition << std::endl;
  
  for(unsigned i(0);i<6;i++) {
    for(unsigned j(0);j<2;j++) {
      o << s << " Trim current " << i;
      if(j==0) o << " measured  = ";
      else     o << " reference = ";
      o << _trimCurrent[i][j] << " A" << std::endl;
    }
  }

  return o;
}

#endif
#endif
