#ifndef DaqStateData_HH
#define DaqStateData_HH

#include <string>
#include <iostream>


class DaqStateData {

public:
  enum {
    versionNumber=0
  };

  enum {
    maxState=9,
    maxTarget=4
  };

  enum StateMachine {
    slwData,
    slow,
    medium,
    fast
  };

  DaqStateData(StateMachine s=slwData);
  
  StateMachine stateMachine() const;
  void         stateMachine(StateMachine s);

  unsigned initialState() const;
  void     initialState(unsigned n);

  unsigned finalState() const;
  void     finalState(unsigned n);
  
  unsigned target() const;
  void     target(unsigned n, unsigned t);

  void command(unsigned n, unsigned t);
  
  std::ostream& print(std::ostream &o, std::string s="") const;


private:
  void reset();

  StateMachine _stateMachine;
  unsigned _initialState;
  unsigned _finalState;
  unsigned _command[maxTarget];
  unsigned _target[maxTarget];
};


#ifdef CALICE_DAQ_ICC

DaqStateData::DaqStateData(StateMachine s) : _stateMachine(s) {
  reset();
}

DaqStateData::StateMachine DaqStateData::stateMachine() const {
  return _stateMachine;
}

void DaqStateData::stateMachine(StateMachine s) {
  _stateMachine=s;
}

unsigned DaqStateData::initialState() const {
  return _initialState;
}

void DaqStateData::initialState(unsigned n) {
  assert(n<=maxState);
  _initialState=n;
  _finalState=0;
}

unsigned DaqStateData::finalState() const {
  return _finalState;
}

void DaqStateData::finalState(unsigned n) {
  assert(n<=maxState);
  _finalState=n;
  for(unsigned i(0);i<maxTarget;i++) {
    if(_target[i]>=_finalState) _target[i]=maxState;
  }
}

unsigned DaqStateData::target() const {
  unsigned t(maxState);
  for(unsigned i(0);i<maxTarget;i++) {
    if(_target[i] <t) t=_target[i];
    if(_command[i]<t) t=_command[i];
  }
  return t;
}

void DaqStateData::target(unsigned n, unsigned t) {
  assert(n<maxTarget);
  _target[n]=t;
}

void DaqStateData::command(unsigned n, unsigned t) {
  assert(n<maxTarget);
  _command[n]=t;
}

void DaqStateData::reset() {
  _initialState=0;
  _finalState=0;
  for(unsigned i(0);i<maxTarget;i++) {
    _target[i]=maxState;
    _command[i]=maxState;
  }
}

std::ostream& DaqStateData::print(std::ostream &o, std::string s) const {
  o << s << "DaqStateData::print()" << std::endl;
  o << s << " State machine = " << _stateMachine << std::endl;
  o << s << " Initial, final states = " << _initialState
    << ", " << _finalState << std::endl;
  o << s << " Target state = " << target() << std::endl;

  for(unsigned i(0);i<maxTarget;i++) {
    o << s << " Target " << i << " = " << _target[i] << std::endl;
    o << s << " Command " << i << " = " << _command[i] << std::endl;
  }

  return o;
}

#endif
#endif
