#ifndef DaqConfiguration_HH
#define DaqConfiguration_HH

#include <vector>
#include <fstream>
#include <iostream>

#include "RcdUserRW.hh"

#include "SubInserter.hh"
#include "SubAccessor.hh"

#include "DaqRunStart.hh"
#include "DaqRunEnd.hh"
#include "DaqConfigurationStart.hh"
#include "DaqConfigurationEnd.hh"
#include "DaqSlowReadout.hh"
#include "DaqAcquisitionStart.hh"
#include "DaqAcquisitionEnd.hh"
#include "DaqSpillStart.hh"
#include "DaqSpillEnd.hh"
#include "DaqTransferStart.hh"
#include "DaqTransferEnd.hh"

#include "DaqRunNumber.hh"


class DaqConfiguration : public RcdUserRW {

public:
  enum Counter {
    cfgInRun,
    slwInRun,slwInCfg,
    acqInRun,acqInCfg,
    splInRun,splInCfg,
    trnInRun,trnInCfg,
    trgInRun,trgInCfg,trgInAcq,
    bstInRun,bstInCfg,bstInAcq,
    evtInRun,evtInCfg,evtInAcq,
    endOfCounterEnum
  };

  DaqConfiguration() {

  }

  virtual ~DaqConfiguration() {
  }

  DaqRunStart runStart() const {
    return _runStartFromRunControl;
  }

  void runStart(DaqRunStart r) {
    _runStartFromRunControl=r;
    assert(_runStartFromRunControl.runType().knownType());
  }

  bool record(RcdRecord &r) {
    if(doPrint(r.recordType())) {
      std::cout << "DaqConfiguration::record()" << std::endl;
      r.RcdHeader::print(std::cout," ") << std::endl;
    }
 
    SubInserter inserter(r);

    UtlPack tid;
    tid.halfWord(1,SubHeader::daq);
    tid.byte(2,0);

    DaqTwoTimer *t(inserter.insert<DaqTwoTimer>(true));
    t->timerId(tid.word());


    // Check record type
    switch (r.recordType()) {

    case RcdHeader::runStart: {
      _count[cfgInRun]=0;
      _count[slwInRun]=0;
      _count[acqInRun]=0;
      _count[splInRun]=0;
      _count[trnInRun]=0;
      _count[trgInRun]=0;
      _count[bstInRun]=0;
      _count[evtInRun]=0;

      SubInserter inserter(r);
      DaqRunStart *d(inserter.insert<DaqRunStart>(true));

      if(_runStartFromRunControl.runType().writeRun()) {
	_runNumber=daqReadRunNumber();
	daqWriteRunNumber(_runNumber+1);
      } else {
	_runNumber=r.recordTime().seconds();
      }

      d->runNumber(_runNumber);
      d->runType(_runStartFromRunControl.runType());
      setRun(*d);
      
      if(doPrint(r.recordType(),1)) d->print(std::cout," ") << std::endl;
      
      break;
    }
      
    case RcdHeader::configurationStart: {
      _count[slwInCfg]=0;
      _count[acqInCfg]=0;
      _count[splInCfg]=0;
      _count[trnInCfg]=0;
      _count[trgInCfg]=0;
      _count[bstInCfg]=0;
      _count[evtInCfg]=0;
          
      _daqConfigurationStart.reset();
      _daqConfigurationStart.configurationNumberInRun(_count[cfgInRun]);
      setConfiguration(_daqConfigurationStart);
     
      SubInserter inserter(r);
      inserter.insert<DaqConfigurationStart>(_daqConfigurationStart);

      if(doPrint(r.recordType(),1))
	_daqConfigurationStart.print(std::cout," ") << std::endl;
      
      _count[cfgInRun]++;

      break;
    }

    case RcdHeader::slowReadout: {
      SubInserter inserter(r);
      DaqSlowReadout *d(inserter.insert<DaqSlowReadout>(true));

      d->slowReadoutNumberInRun(          _count[slwInRun]);
      d->slowReadoutNumberInConfiguration(_count[slwInCfg]);
      
      if(doPrint(r.recordType(),1)) d->print(std::cout," ") << std::endl;

      _count[slwInRun]++;
      _count[slwInCfg]++;
      
      break;
    }

    case RcdHeader::acquisitionStart: {
      _count[trgInAcq]=0;
      _count[bstInAcq]=0;
      _count[evtInAcq]=0;
    
      SubInserter inserter(r);
      DaqAcquisitionStart *d(inserter.insert<DaqAcquisitionStart>(true));

      d->acquisitionNumberInRun(          _count[acqInRun]);
      d->acquisitionNumberInConfiguration(_count[acqInCfg]);
      d->maximumNumberOfEventsInAcquisition(_daqConfigurationStart.maximumNumberOfEventsInAcquisition());
      d->maximumTimeOfAcquisition(_daqConfigurationStart.maximumTimeOfAcquisition());

      if(doPrint(r.recordType(),1)) d->print(std::cout," ") << std::endl;

      _count[acqInRun]++;
      _count[acqInCfg]++;
      
      break;
    }
      
    case RcdHeader::spillStart: {
      SubInserter inserter(r);
      DaqSpillStart *d(inserter.insert<DaqSpillStart>(true));

      d->spillNumberInRun(          _count[splInRun]);
      d->spillNumberInConfiguration(_count[splInCfg]);
      d->maximumNumberOfEventsInSpill(_daqConfigurationStart.maximumNumberOfEventsInSpill());
      d->maximumTimeOfSpill(_daqConfigurationStart.maximumTimeOfSpill());

      if(doPrint(r.recordType(),1)) d->print(std::cout," ") << std::endl;
    
      _count[splInRun]++;
      _count[splInCfg]++;
      
      break;
    }
      
    case RcdHeader::transferStart: {
      SubInserter inserter(r);
      DaqTransferStart *d(inserter.insert<DaqTransferStart>(true));

      d->transferNumberInRun(          _count[trnInRun]);
      d->transferNumberInConfiguration(_count[trnInCfg]);
      
      if(doPrint(r.recordType(),1)) d->print(std::cout," ") << std::endl;

      _count[trnInRun]++;
      _count[trnInCfg]++;
      
      break;
    }
      
    case RcdHeader::trigger: {
      SubInserter inserter(r);
      DaqEvent *d(inserter.insert<DaqEvent>(true));
      
      d->eventNumberInRun(          _count[trgInRun]);
      d->eventNumberInConfiguration(_count[trgInCfg]);
      d->eventNumberInAcquisition(  _count[trgInAcq]);

      if(doPrint(r.recordType(),1)) d->print(std::cout," ") << std::endl;
      
      _count[trgInRun]++;
      _count[trgInCfg]++;
      _count[trgInAcq]++;
      
      break;
    }

    case RcdHeader::triggerBurst: {
      SubInserter inserter(r);
      DaqBurstStart *d(inserter.insert<DaqBurstStart>(true));

      d->burstNumberInRun(          _count[bstInRun]);
      d->burstNumberInConfiguration(_count[bstInCfg]);
      d->burstNumberInAcquisition(  _count[bstInAcq]);

      d->firstTriggerNumberInRun(          _count[trgInRun]);
      d->firstTriggerNumberInConfiguration(_count[trgInCfg]);
      d->firstTriggerNumberInAcquisition(  _count[trgInAcq]);

      d->maximumNumberOfExtraTriggersInBurst(_maximumNumberOfExtraTriggersInBurst);
      d->maximumTimeOfBurst(_maximumTimeOfBurst);

      if(doPrint(r.recordType(),1)) d->print(std::cout," ") << std::endl;
      
      _count[bstInRun]++;
      _count[bstInCfg]++;
      _count[bstInAcq]++;

      // Trigger counters incremented by DaqReadout

      break;
    }

    case RcdHeader::event: {
      SubInserter inserter(r);
      DaqEvent *d(inserter.insert<DaqEvent>(true));
      
      d->eventNumberInRun(          _count[evtInRun]);
      d->eventNumberInConfiguration(_count[evtInCfg]);
      d->eventNumberInAcquisition(  _count[evtInAcq]);

      if(doPrint(r.recordType(),1)) d->print(std::cout," ") << std::endl;
      
      _count[evtInRun]++;
      _count[evtInCfg]++;
      _count[evtInAcq]++;
      
      break;
    }
      
    default: {
      break;
    }
    };

    // Close off overall timer                                                                                                                
    t->setEndTime();
    if(doPrint(r.recordType(),1)) t->print(std::cout," ") << std::endl;

    return true;
  }


  virtual void setRun(DaqRunStart &d) const {
    const unsigned char v(_runStartFromRunControl.runType().version());

    switch(_runStartFromRunControl.runType().type()) {

    case DaqRunType::daqTest: {
      break;
    }

    case DaqRunType::crcTest: {
      break;
    }
    case DaqRunType::crcNoise: {
      break;
    }
    case DaqRunType::crcBeParameters: {
      if(v== 0) d.maximumNumberOfConfigurationsInRun(256);
      if(v== 1) d.maximumNumberOfConfigurationsInRun(256);
      if(v== 2) d.maximumNumberOfConfigurationsInRun(256);
      if(v== 3) d.maximumNumberOfConfigurationsInRun(256);
      if(v== 4) d.maximumNumberOfConfigurationsInRun(256);
      if(v== 5) d.maximumNumberOfConfigurationsInRun(4096);
      if(v== 6) d.maximumNumberOfConfigurationsInRun(4);
      if(v== 7) d.maximumNumberOfConfigurationsInRun(256);
      if(v== 8) d.maximumNumberOfConfigurationsInRun(4);
      if(v== 9) d.maximumNumberOfConfigurationsInRun(65536);
      if(v==10) d.maximumNumberOfConfigurationsInRun(65536);
      break;
    }
    case DaqRunType::crcFeParameters: {
      if(v== 0) d.maximumNumberOfConfigurationsInRun(4);
      if(v== 1) d.maximumNumberOfConfigurationsInRun(4);
      if(v== 2) d.maximumNumberOfConfigurationsInRun(18);
      if(v== 3) d.maximumNumberOfConfigurationsInRun(32);
      if(v== 4) d.maximumNumberOfConfigurationsInRun(32);
      if(v== 5) d.maximumNumberOfConfigurationsInRun(16);
      if(v== 6) d.maximumNumberOfConfigurationsInRun(128);
      break;
    }
    case DaqRunType::crcIntDac: {
      break;
    }
    case DaqRunType::crcIntDacScan: {
      d.maximumNumberOfConfigurationsInRun(2*v+4);
      break;
    }
    case DaqRunType::crcExtDac: {
      break;
    }
    case DaqRunType::crcExtDacScan: {
      d.maximumNumberOfConfigurationsInRun(2*v+2);
      break;
    }
    case DaqRunType::crcFakeEvent: {
      break;
    }
    case DaqRunType::crcModeTest: {
      d.maximumNumberOfConfigurationsInRun(21);
      break;
    }

    case DaqRunType::trgTest: {
      break;
    }
    case DaqRunType::trgParameters: {
      break;
    }
    case DaqRunType::trgSpill: {
      break;
    }
    case DaqRunType::trgNoise: {
      break;
    }

    case DaqRunType::emcTest: {
      break;
    }
    case DaqRunType::emcNoise: {
      break;
    }
    case DaqRunType::emcFeParameters: {
      break;
    }
    case DaqRunType::emcVfeDac: {
      break;
    }
    case DaqRunType::emcVfeDacScan: {
      d.maximumNumberOfConfigurationsInRun(6*(v+1)+4);
      break;
    }
    case DaqRunType::emcVfeHoldScan: {
      d.maximumNumberOfConfigurationsInRun(6*(v+1)+4);
      break;
    }
    case DaqRunType::emcTrgTiming: {
      break;
    }
    case DaqRunType::emcTrgTimingScan: {
      d.maximumNumberOfConfigurationsInRun(56);
      break;
    }
    case DaqRunType::emcBeam: {
      break;
    }
    case DaqRunType::emcBeamHoldScan: {
      break;
    }
    case DaqRunType::emcCosmics: {
      break;
    }
    case DaqRunType::emcCosmicsHoldScan: {
      break;
    }

    case DaqRunType::sceTest: {
      break;
    }
    case DaqRunType::sceCmNoise:
    case DaqRunType::scePmNoise: {
      break;
    }
    case DaqRunType::sceDacScan: {
      d.maximumNumberOfConfigurationsInRun(2*v+1);
      break;
    }
    case DaqRunType::sceAnalogOut: {
      break;
    }
    case DaqRunType::sceCmAsic: {
      break;
    }
    case DaqRunType::sceCmAsicVcalibScan: {
      d.maximumNumberOfConfigurationsInRun(2*(v+1));
      break;
    }
    case DaqRunType::sceCmAsicHoldScan: {
      d.maximumNumberOfConfigurationsInRun(v+1);
      break;
    }
    case DaqRunType::scePmAsic: {
      break;
    }
    case DaqRunType::scePmAsicVcalibScan: {
      d.maximumNumberOfConfigurationsInRun(2*(v+1));
      break;
    }
    case DaqRunType::scePmAsicHoldScan: {
      d.maximumNumberOfConfigurationsInRun(v+1);
      break;
    }
    case DaqRunType::sceCmLed: {
      break;
    }
    case DaqRunType::sceCmLedVcalibScan: {
      //d.maximumNumberOfConfigurationsInRun(13); //default until 18.10.06
      //d.maximumNumberOfConfigurationsInRun(28); //default until 20.10.06
      d.maximumNumberOfConfigurationsInRun(21);   //default
      //d.maximumNumberOfConfigurationsInRun(532); //detailed vcalibscan 1 -- not default
      //d.maximumNumberOfConfigurationsInRun(341); //detailed vcalibscan 2 -- not default
      //if(v==1) d.maximumNumberOfConfigurationsInRun(131); changed by Kurt & Alex 2008/05/16
      if(v==1) d.maximumNumberOfConfigurationsInRun(131); 
      if(v==2) d.maximumNumberOfConfigurationsInRun(40); // this versioning is not optimal, because it sets also the fast acquisition flag => has to be changed
      if(v==3) d.maximumNumberOfConfigurationsInRun(80);
      break;
    }
    case DaqRunType::sceCmLedHoldScan: {
      d.maximumNumberOfConfigurationsInRun(100);
      break;
    }
    case DaqRunType::scePmLed: {
      break;
    }
    case DaqRunType::scePmLedVcalibScan: {
      //d.maximumNumberOfConfigurationsInRun(43); //default until 18.10.06
      //d.maximumNumberOfConfigurationsInRun(38); //default until 20.10.06
      d.maximumNumberOfConfigurationsInRun(32); //default
      //d.maximumNumberOfConfigurationsInRun(532); //detailed vcalibscan 1 -- not default
      //d.maximumNumberOfConfigurationsInRun(341); //detailed vcalibscan 2 -- not default
      if(v==1) d.maximumNumberOfConfigurationsInRun(131);
      if(v==2) d.maximumNumberOfConfigurationsInRun(40); // this versioning is not optimal, because it sets also the fast acquisition flag => has to be changed
      if(v==3) d.maximumNumberOfConfigurationsInRun(80);      
      //d.maximumNumberOfConfigurationsInRun(v+1);
      break;
    }
    case DaqRunType::scePmLedHoldScan: {
      d.maximumNumberOfConfigurationsInRun(100);
      break;
    }
    case DaqRunType::sceScintillatorHoldScan: {
      d.maximumNumberOfConfigurationsInRun(32);
      break;
    }
    case DaqRunType::sceBeam: {
      break;
    }
    case DaqRunType::sceBeamHoldScan: {
      break;
    }
    case DaqRunType::sceBeamStage: {
      break;
    }
    case DaqRunType::sceBeamStageScan: {
      break;
    }
    case DaqRunType::sceCosmics: {
      break;
    }
    case DaqRunType::sceCosmicsHoldScan: {
      break;
    }
    case DaqRunType::sceExpert: {
      if (v == 1 || v == 2) d.maximumNumberOfConfigurationsInRun(1000);
      break;
    }
    case DaqRunType::sceGain: {
      d.maximumNumberOfConfigurationsInRun(4);
      break;
    }

    case DaqRunType::ahcTest: {
      break;
    }
    case DaqRunType::ahcCmNoise:
    case DaqRunType::ahcPmNoise: {
      break;
    }
    case DaqRunType::ahcDacScan: {
      d.maximumNumberOfConfigurationsInRun(2*v+1);
      break;
    }
    case DaqRunType::ahcAnalogOut: {
      break;
    }
    case DaqRunType::ahcCmAsic: {
      break;
    }
    case DaqRunType::ahcCmAsicVcalibScan: {
      d.maximumNumberOfConfigurationsInRun(2*(v+1));
      break;
    }
    case DaqRunType::ahcCmAsicHoldScan: {
      d.maximumNumberOfConfigurationsInRun(v+1);
      break;
    }
    case DaqRunType::ahcPmAsic: {
      break;
    }
    case DaqRunType::ahcPmAsicVcalibScan: {
      d.maximumNumberOfConfigurationsInRun(2*(v+1));
      break;
    }
    case DaqRunType::ahcPmAsicHoldScan: {
      d.maximumNumberOfConfigurationsInRun(v+1);
      break;
    }
    case DaqRunType::ahcCmLed: {
      break;
    }
    case DaqRunType::ahcCmLedVcalibScan: {
      //d.maximumNumberOfConfigurationsInRun(13); //default until 18.10.06
      //d.maximumNumberOfConfigurationsInRun(28); //default until 20.10.06
      d.maximumNumberOfConfigurationsInRun(21);   //default
      //d.maximumNumberOfConfigurationsInRun(532); //detailed vcalibscan 1 -- not default
      //d.maximumNumberOfConfigurationsInRun(341); //detailed vcalibscan 2 -- not default
      if(v==1) d.maximumNumberOfConfigurationsInRun(131); 
      if(v==2) d.maximumNumberOfConfigurationsInRun(40); // this versioning is not optimal, because it sets also the fast acquisition flag => has to be changed
      if(v==3) d.maximumNumberOfConfigurationsInRun(80);
      break;
    }
    case DaqRunType::ahcCmLedHoldScan: {
      d.maximumNumberOfConfigurationsInRun(100);
      break;
    }
    case DaqRunType::ahcPmLed: {
      break;
    }
    case DaqRunType::ahcPmLedVcalibScan: {
      //d.maximumNumberOfConfigurationsInRun(43); //default until 18.10.06
      //d.maximumNumberOfConfigurationsInRun(38); //default until 20.10.06
      d.maximumNumberOfConfigurationsInRun(32); //default
      //d.maximumNumberOfConfigurationsInRun(65); // SeS 070419
      //d.maximumNumberOfConfigurationsInRun(532); //detailed vcalibscan 1 -- not default
      //d.maximumNumberOfConfigurationsInRun(341); //detailed vcalibscan 2 -- not default
      if(v==1) d.maximumNumberOfConfigurationsInRun(131);
      if(v==2) d.maximumNumberOfConfigurationsInRun(40); // this versioning is not optimal, because it sets also the fast acquisition flag => has to be changed
      if(v==3) d.maximumNumberOfConfigurationsInRun(80);      
      //d.maximumNumberOfConfigurationsInRun(v+1);
      break;
    }
    case DaqRunType::ahcPmLedHoldScan: {
      d.maximumNumberOfConfigurationsInRun(100);
      break;
    }
    case DaqRunType::ahcScintillatorHoldScan: {
      d.maximumNumberOfConfigurationsInRun(32);
      break;
    }
    case DaqRunType::ahcBeam: {
      break;
    }
    case DaqRunType::ahcBeamHoldScan: {
      break;
    }
    case DaqRunType::ahcBeamStage: {
      break;
    }
    case DaqRunType::ahcBeamStageScan: {
      break;
    }
    case DaqRunType::ahcCosmics: {
      break;
    }
    case DaqRunType::ahcCosmicsHoldScan: {
      break;
    }
    case DaqRunType::ahcExpert: {
      if (v == 1 || v == 2) d.maximumNumberOfConfigurationsInRun(1000);
      break;
    }
    case DaqRunType::ahcGain: {
      d.maximumNumberOfConfigurationsInRun(11);  // this has to be synchronos with AhcConfiguration.hh, fixed again on 2007 July 03, Beni
      break;
    }

    case DaqRunType::dhcTest: {
      break;
    }
    case DaqRunType::dhcNoise: {
      break;
    }
    case DaqRunType::dhcBeam: {
      break;
    }
    case DaqRunType::dhcCosmics: {
      break;
    }
    case DaqRunType::dhcQinj: {
      d.maximumNumberOfConfigurationsInRun(4);
      break;
    }
    case DaqRunType::dhcQinjScan: {
      d.maximumNumberOfConfigurationsInRun((v&0x30)*4);
      break;
    }

    case DaqRunType::dheTest: {
      break;
    }
    case DaqRunType::dheNoise: {
      break;
    }
    case DaqRunType::dheBeam: {
      break;
    }
    case DaqRunType::dheCosmics: {
      break;
    }

    case DaqRunType::tcmCalPedestal: //KF added 022406
    case DaqRunType::tcmPhysPedestal: //KF added 022406
    case DaqRunType::tcmCalLed: //KF added 022406
    case DaqRunType::tcmPhysLed: //KF added 022406
    case DaqRunType::tcmCosmics: {//KF added 022406 //same as tcmBeam for now, functionality to be enhanced later
      break;
    }
    case DaqRunType::tcmBeam: { //KF added
      break;
    }
    case DaqRunType::tcmBeamHoldScan: {
      d.maximumNumberOfConfigurationsInRun(1000);
      break;
    }

    case DaqRunType::bmlTest: {
      break;
    }
    case DaqRunType::bmlNoise: {
      break;
    }
    case DaqRunType::bmlInternalTest: {
      break;
    }
    case DaqRunType::bmlBeam: {
      break;
    }

    case DaqRunType::slowTest: {	
      d.maximumNumberOfAcquisitionsInRun(0);
      d.maximumNumberOfEventsInRun(0);
      break;
    }
    case DaqRunType::slowMonitor: {
      d.maximumNumberOfAcquisitionsInRun(0);
      d.maximumNumberOfEventsInRun(0);
      break;
    }

    case DaqRunType::beamTest: {
      break;
    }
    case DaqRunType::beamNoise: {
      break;
    }
    case DaqRunType::beamData: {
      break;
    }
    case DaqRunType::beamHoldScan: {
      break;
    }
    case DaqRunType::beamStageScan: {   // inserted 2007 July 3 Beni
      break;
    }
    case DaqRunType::cosmicsTest: {
      break;
    }
    case DaqRunType::cosmicsNoise: {
      break;
    }
    case DaqRunType::cosmicsData: {
      break;
    }
    case DaqRunType::cosmicsHoldScan: {
      break;
    }

    default: {
      // We missed a run type
      assert(false);
      break;
    }
    };

    // Reset limits if endless run from run control
    if(_runStartFromRunControl.runType().endlessRun()) {
      d.maximumNumberOfConfigurationsInRun(0xffffffff);
      d.maximumNumberOfAcquisitionsInRun(0xffffffff);
      d.maximumNumberOfEventsInRun(0xffffffff);
      d.maximumTimeOfRun(UtlTimeDifference(0x7fffffff,999999));
    }

    // Reset limits if smaller from run control
    if(d.maximumNumberOfConfigurationsInRun()>
       _runStartFromRunControl.maximumNumberOfConfigurationsInRun())
      d.maximumNumberOfConfigurationsInRun(_runStartFromRunControl.maximumNumberOfConfigurationsInRun());
    
    if(d.maximumNumberOfAcquisitionsInRun()>
       _runStartFromRunControl.maximumNumberOfAcquisitionsInRun())
      d.maximumNumberOfAcquisitionsInRun(_runStartFromRunControl.maximumNumberOfAcquisitionsInRun());

    if(d.maximumNumberOfEventsInRun()>
       _runStartFromRunControl.maximumNumberOfEventsInRun())
      d.maximumNumberOfEventsInRun(_runStartFromRunControl.maximumNumberOfEventsInRun());

    if(d.maximumTimeOfRun()>
       _runStartFromRunControl.maximumTimeOfRun())
      d.maximumTimeOfRun(_runStartFromRunControl.maximumTimeOfRun());
  }

  virtual void setConfiguration(DaqConfigurationStart &d) const {
    const unsigned iCfg(d.configurationNumberInRun());

    //const unsigned char v(_runStartFromRunControl.runType().version());
    const UtlPack u(_runStartFromRunControl.runType().version());

    // Overall defaults
    d.maximumNumberOfEventsInAcquisition(4000);
    d.maximumTimeOfEvent(UtlTimeDifference(1)); // 1second
    d.maximumTimeOfConfiguration(UtlTimeDifference(60*60)); // 1hour
    d.minimumTimeBeforeSlowReadout(UtlTimeDifference(5*60)); // 5mins
    
    // Select on run type
    switch(_runStartFromRunControl.runType().type()) {

    case DaqRunType::daqTest: {
      break;
    }

    case DaqRunType::trgTest: {
      break;
    }
    case DaqRunType::trgParameters: {
      break;
    }
    case DaqRunType::trgNoise: {
      break;
    }
    case DaqRunType::trgSpill: {
      d.maximumTimeOfSpill(UtlTimeDifference(1,0));
      break;
    }

    case DaqRunType::crcTest: {
      break;
    }
    case DaqRunType::crcNoise: {
      d.maximumNumberOfEventsInAcquisition(500);
      break;
    }
    case DaqRunType::crcBeParameters: {
      d.maximumNumberOfEventsInConfiguration(500);
      break;
    }
    case DaqRunType::crcFeParameters: {
      d.maximumNumberOfEventsInConfiguration(500);
      break;
    }
    case DaqRunType::crcIntDac: {
      break;
    }
    case DaqRunType::crcIntDacScan: {
      d.maximumNumberOfEventsInConfiguration(500);
      break;
    }
    case DaqRunType::crcExtDac: {
      break;
    }
    case DaqRunType::crcExtDacScan: {
      d.maximumNumberOfEventsInConfiguration(500);
      break;
    }
    case DaqRunType::crcFakeEvent: {
      d.maximumNumberOfEventsInConfiguration(500);
      break;
    }
    case DaqRunType::crcModeTest: {
      d.maximumNumberOfAcquisitionsInConfiguration(8);
      unsigned i(iCfg%7);
      unsigned j((iCfg/7)%3);
      if(j==1) d.maximumNumberOfEventsInAcquisition(500);
      else     d.maximumNumberOfEventsInAcquisition(500+100*i);
      break;
    }

    case DaqRunType::emcTest: {
      break;
    }
    case DaqRunType::emcNoise: {
      //if((v&0x80)==0) d.maximumNumberOfEventsInAcquisition(500);
      if(u.bit(7)) d.maximumNumberOfEventsInAcquisition(500);
      else         d.maximumNumberOfEventsInAcquisition(100);
      break;
    }
    case DaqRunType::emcVfeDac: {
      break;
    }
    case DaqRunType::emcVfeDacScan: {
      d.maximumNumberOfEventsInConfiguration(500);
      break;
    }
    case DaqRunType::emcVfeHoldScan: {
      d.maximumNumberOfEventsInConfiguration(500);
      break;
    }
    case DaqRunType::emcTrgTiming: {
      break;
    }
    case DaqRunType::emcTrgTimingScan: {
      d.maximumNumberOfEventsInConfiguration(500);
      break;
    }

    case DaqRunType::sceTest: {
      break;
    }
    case DaqRunType::sceCmNoise:
    case DaqRunType::scePmNoise: {
      if(u.bit(1)) d.maximumNumberOfEventsInAcquisition(100);
      break;
    }
    case DaqRunType::sceDacScan: {
      d.maximumNumberOfEventsInConfiguration(500);
      break;
    }
    case DaqRunType::sceAnalogOut: {
      break;
    }
    case DaqRunType::sceCmAsic: {
      break;
    }
    case DaqRunType::sceCmAsicVcalibScan: {
      d.maximumNumberOfEventsInConfiguration(500);
      break;
    }
    case DaqRunType::sceCmAsicHoldScan: {
      d.maximumNumberOfEventsInConfiguration(500);
      break;
    }
    case DaqRunType::scePmAsic: {
      break;
    }
    case DaqRunType::scePmAsicVcalibScan: {
      d.maximumNumberOfEventsInConfiguration(500);
      break;
    }
    case DaqRunType::scePmAsicHoldScan: {
      d.maximumNumberOfEventsInConfiguration(500);
      break;
    }
    case DaqRunType::sceCmLed: {
      if(u.bit(1)) d.maximumNumberOfEventsInAcquisition(100);
      break;
    }
    case DaqRunType::sceCmLedVcalibScan: {
      if(u.bit(1)) d.maximumNumberOfEventsInAcquisition(100);
      d.maximumNumberOfEventsInConfiguration(1000);
      break;
    }
    case DaqRunType::sceCmLedHoldScan: {
      if(u.bit(1)) d.maximumNumberOfEventsInAcquisition(100);
      d.maximumNumberOfEventsInConfiguration(500);
      break;
    }
    case DaqRunType::scePmLed: {
      if(u.bit(1)) d.maximumNumberOfEventsInAcquisition(100);
      break;
    }
    case DaqRunType::scePmLedVcalibScan: {
      if(u.bit(1)) d.maximumNumberOfEventsInAcquisition(100);
      d.maximumNumberOfEventsInConfiguration(1000);
      break;
    }
    case DaqRunType::scePmLedHoldScan: {
      if(u.bit(1)) d.maximumNumberOfEventsInAcquisition(100);
      d.maximumNumberOfEventsInConfiguration(500);
      break;
    }
    case DaqRunType::sceScintillatorHoldScan: {
      d.maximumNumberOfEventsInConfiguration(500);
      break;
    }
    case DaqRunType::sceExpert: {
      if(u.bit(1)) d.maximumNumberOfEventsInAcquisition(100);
      break;
    }
    case DaqRunType::sceGain: {
      d.maximumNumberOfEventsInConfiguration(20000);
      break;
    }  

    case DaqRunType::ahcTest: {
      break;
    }
    case DaqRunType::ahcCmNoise:
    case DaqRunType::ahcPmNoise: {
      if(u.bit(1)) d.maximumNumberOfEventsInAcquisition(100);
      break;
    }
    case DaqRunType::ahcDacScan: {
      d.maximumNumberOfEventsInConfiguration(500);
      break;
    }
    case DaqRunType::ahcAnalogOut: {
      break;
    }
    case DaqRunType::ahcCmAsic: {
      break;
    }
    case DaqRunType::ahcCmAsicVcalibScan: {
      d.maximumNumberOfEventsInConfiguration(500);
      break;
    }
    case DaqRunType::ahcCmAsicHoldScan: {
      d.maximumNumberOfEventsInConfiguration(500);
      break;
    }
    case DaqRunType::ahcPmAsic: {
      break;
    }
    case DaqRunType::ahcPmAsicVcalibScan: {
      d.maximumNumberOfEventsInConfiguration(500);
      break;
    }
    case DaqRunType::ahcPmAsicHoldScan: {
      d.maximumNumberOfEventsInConfiguration(500);
      break;
    }
    case DaqRunType::ahcCmLed: {
      if(u.bit(1)) d.maximumNumberOfEventsInAcquisition(100);
      break;
    }
    case DaqRunType::ahcCmLedVcalibScan: {
      if(u.bit(1)) d.maximumNumberOfEventsInAcquisition(100);
      d.maximumNumberOfEventsInConfiguration(1000);
      break;
    }
    case DaqRunType::ahcCmLedHoldScan: {
      if(u.bit(1)) d.maximumNumberOfEventsInAcquisition(100);
      d.maximumNumberOfEventsInConfiguration(500);
      break;
    }
    case DaqRunType::ahcPmLed: {
      if(u.bit(1)) d.maximumNumberOfEventsInAcquisition(100);
      break;
    }
    case DaqRunType::ahcPmLedVcalibScan: {
      if(u.bit(1)) d.maximumNumberOfEventsInAcquisition(100);
      d.maximumNumberOfEventsInConfiguration(1000);
      break;
    }
    case DaqRunType::ahcPmLedHoldScan: {
      if(u.bit(1)) d.maximumNumberOfEventsInAcquisition(100);
      d.maximumNumberOfEventsInConfiguration(500);
      break;
    }
    case DaqRunType::ahcScintillatorHoldScan: {
      d.maximumNumberOfEventsInConfiguration(500);
      break;
    }
    case DaqRunType::ahcExpert: {
      if(u.bit(1)) d.maximumNumberOfEventsInAcquisition(100);
      break;
    }
    case DaqRunType::ahcGain: {
      d.maximumNumberOfEventsInConfiguration(15000);           // reduced to 15000 to save time, quality to be checked, 2007 July 3, Beni
      break;
    }  

    case DaqRunType::dhcTest: {
      break;
    }
    case DaqRunType::dhcNoise: {
      d.maximumNumberOfEventsInConfiguration(100);
      break;
    }
    case DaqRunType::dhcQinj: 
    case DaqRunType::dhcQinjScan: {
      d.maximumNumberOfEventsInConfiguration(500);
      break;
    }

    case DaqRunType::dheTest: {
      break;
    }
    case DaqRunType::dheNoise: {
      break;
    }

    case DaqRunType::tcmCalPedestal:
    case DaqRunType::tcmPhysPedestal:
    case DaqRunType::tcmCalLed:
    case DaqRunType::tcmPhysLed: {
      d.maximumNumberOfEventsInConfiguration(10000);
      break;
    }

    case DaqRunType::bmlTest: {
      break;
    }
    case DaqRunType::bmlNoise: {
      break;
    }
    case DaqRunType::bmlInternalTest: {
      break;
    }

    case DaqRunType::slowTest: {
      break;
    }
    case DaqRunType::slowMonitor: {
      d.maximumNumberOfAcquisitionsInConfiguration(0);
      d.maximumNumberOfEventsInConfiguration(0);
      d.maximumNumberOfEventsInAcquisition(0);
      d.minimumTimeBeforeSlowReadout(UtlTimeDifference(60)); // 1min
      break;
    }

    case DaqRunType::emcBeam:
    case DaqRunType::emcBeamHoldScan:



    case DaqRunType::ahcBeam:
  //case DaqRunType::ahcBeamHoldScan:
    case DaqRunType::ahcBeamStage:
    case DaqRunType::ahcBeamStageScan:

    case DaqRunType::dhcBeam:

    case DaqRunType::dheBeam:

    case DaqRunType::tcmBeam:
    case DaqRunType::tcmBeamHoldScan:

    case DaqRunType::bmlBeam:

    case DaqRunType::beamTest:
    case DaqRunType::beamNoise:
    case DaqRunType::beamData:
    case DaqRunType::beamHoldScan: 
    case DaqRunType::beamStageScan: {                          // inserted stage scan 2007 July 3 Beni
      if((iCfg%3)<2) { // Pedestals or LED
	//d.maximumNumberOfAcquisitionsInConfiguration(1);
	//d.maximumNumberOfEventsInAcquisition(500);
	d.maximumNumberOfEventsInConfiguration(500);

	d.maximumTimeOfEvent(UtlTimeDifference(1)); // 1s
#ifdef CERN_SETTINGS
	d.maximumTimeOfSpill(UtlTimeDifference(17)); // 17s
#endif
#ifdef FNAL_SETTINGS
	d.maximumTimeOfSpill(UtlTimeDifference(120)); // 2mins
#endif

      } else { // Data

	d.maximumTimeOfEvent(UtlTimeDifference(1)); // 1s

#ifdef DESY_SETTINGS
	d.maximumNumberOfEventsInAcquisition(500);
	d.maximumTimeOfEvent(UtlTimeDifference(60*60));
	d.maximumTimeOfConfiguration(UtlTimeDifference(48*60*60));
	//	d.maximumTimeOfConfiguration(UtlTimeDifference(15*60,0));

	//d.maximumNumberOfEventsInConfiguration(10000);
	d.maximumNumberOfEventsInConfiguration(50000);

	//d.maximumNumberOfEventsInAcquisition(32);          // TDC limit
	//d.maximumNumberOfEventsInAcquisition(12);
	
	/* 08.01.07 commented out: no TDC in use
	  d.maximumNumberOfEventsInSpill(32);          // TDC limit
	  //d.maximumTimeOfSpill(UtlTimeDifference(0,60000)); // 60ms
	  //d.maximumTimeOfSpill(UtlTimeDifference(0,40000)); // 40ms
	  //d.maximumTimeOfSpill(UtlTimeDifference(0,100000)); // 100ms
	  d.maximumTimeOfSpill(UtlTimeDifference(1));

	  d.maximumTimeOfEvent(UtlTimeDifference(0,900000)); // 0.9s
	  //d.maximumTimeOfEvent(UtlTimeDifference(1));
	*/
#endif

#ifdef CERN_SETTINGS
	d.maximumTimeOfConfiguration(UtlTimeDifference(15*60,0));
	d.maximumNumberOfEventsInConfiguration(10000);
	d.maximumTimeOfSpill(UtlTimeDifference(17)); // 17s
#endif
#ifdef FNAL_SETTINGS
	d.maximumTimeOfConfiguration(UtlTimeDifference(20*60,0));
	d.maximumNumberOfEventsInConfiguration(30000); // 20 spills x 2000 events
	if(_runStartFromRunControl.runType().type()==DaqRunType::beamHoldScan)
	  d.maximumNumberOfEventsInConfiguration(10000); // fast holscan change by Beni 20080505
	d.maximumTimeOfSpill(UtlTimeDifference(120)); // 2mins
#endif

      }
      break;
    }


    case DaqRunType::sceBeam:
  //case DaqRunType::sceBeamHoldScan:
    case DaqRunType::sceBeamStage:
    case DaqRunType::sceBeamStageScan:{
      if((iCfg%3)<2) { // Pedestals or LED
	//d.maximumNumberOfAcquisitionsInConfiguration(1);
	//d.maximumNumberOfEventsInAcquisition(500);
	d.maximumNumberOfEventsInConfiguration(500);

	d.maximumTimeOfEvent(UtlTimeDifference(1)); // 1s
#ifdef CERN_SETTINGS
	d.maximumTimeOfSpill(UtlTimeDifference(17)); // 17s
#endif
#ifdef FNAL_SETTINGS
	d.maximumTimeOfSpill(UtlTimeDifference(120)); // 2mins
#endif

      } else { // Data

	d.maximumTimeOfEvent(UtlTimeDifference(1)); // 1s
#ifdef DESY_SETTINGS
	d.maximumNumberOfEventsInAcquisition(500);
	d.maximumTimeOfEvent(UtlTimeDifference(60*60));
	d.maximumTimeOfConfiguration(UtlTimeDifference(48*60*60));
	//	d.maximumTimeOfConfiguration(UtlTimeDifference(15*60,0));

	//d.maximumNumberOfEventsInConfiguration(10000);
	d.maximumNumberOfEventsInConfiguration(10000); // this is the number of events in each beam configuration (stage position)

	//d.maximumNumberOfEventsInAcquisition(32);          // TDC limit
	//d.maximumNumberOfEventsInAcquisition(12);
	
	/* 08.01.07 commented out: no TDC in use
	  d.maximumNumberOfEventsInSpill(32);          // TDC limit
	  //d.maximumTimeOfSpill(UtlTimeDifference(0,60000)); // 60ms
	  //d.maximumTimeOfSpill(UtlTimeDifference(0,40000)); // 40ms
	  //d.maximumTimeOfSpill(UtlTimeDifference(0,100000)); // 100ms
	  d.maximumTimeOfSpill(UtlTimeDifference(1));

	  d.maximumTimeOfEvent(UtlTimeDifference(0,900000)); // 0.9s
	  //d.maximumTimeOfEvent(UtlTimeDifference(1));
	*/
#endif

#ifdef CERN_SETTINGS
	d.maximumTimeOfConfiguration(UtlTimeDifference(15*60,0));
	d.maximumNumberOfAcquisitionsInConfiguration(20);
	d.maximumTimeOfSpill(UtlTimeDifference(17)); // 17s
#endif
#ifdef FNAL_SETTINGS
	d.maximumTimeOfConfiguration(UtlTimeDifference(15*60,0));
	d.maximumNumberOfAcquisitionsInConfiguration(20);
	d.maximumTimeOfSpill(UtlTimeDifference(120)); // 2mins
#endif

      }
      break;
    }

    case DaqRunType::sceBeamHoldScan: {
      d.maximumNumberOfAcquisitionsInConfiguration(1);
      d.maximumNumberOfEventsInAcquisition(2000);
      break;
    }
    case DaqRunType::ahcBeamHoldScan: {
      d.maximumNumberOfAcquisitionsInConfiguration(1);
      d.maximumNumberOfEventsInAcquisition(500);
      //d.maximumTimeOfConfiguration(UtlTimeDifference(5*60,0));
      break;
    }

    case DaqRunType::emcCosmics:
    case DaqRunType::emcCosmicsHoldScan:

    case DaqRunType::sceCosmics:
    case DaqRunType::sceCosmicsHoldScan:

    case DaqRunType::ahcCosmics:
    case DaqRunType::ahcCosmicsHoldScan:

    case DaqRunType::dhcCosmics:

    case DaqRunType::dheCosmics:

    case DaqRunType::tcmCosmics:
    case DaqRunType::tcmCosmicsHoldScan:

    case DaqRunType::cosmicsTest:
    case DaqRunType::cosmicsNoise:
    case DaqRunType::cosmicsData:
    case DaqRunType::cosmicsHoldScan: {
      if((iCfg%3)<2) { // Pedestals or LED
	//d.maximumNumberOfAcquisitionsInConfiguration(1);
	//d.maximumNumberOfEventsInAcquisition(500);
	d.maximumNumberOfEventsInConfiguration(500);


#ifdef NOT_DESY_SETTINGS
	d.maximumNumberOfEventsInSpill(2000);
	d.maximumTimeOfSpill(UtlTimeDifference(17)); // 17s
	d.maximumTimeOfEvent(UtlTimeDifference(1)); // 1s
#endif
      } else { // Data

#ifdef DESY_SETTINGS
	d.maximumNumberOfEventsInAcquisition(500);

	d.maximumTimeOfConfiguration(UtlTimeDifference(15*60,0));

	//d.maximumNumberOfEventsInConfiguration(10000);
	d.maximumNumberOfEventsInConfiguration(5000); // Goetz requested reduction from 10k 22/5/06

	//d.maximumNumberOfEventsInAcquisition(32);          // TDC limit
	//d.maximumNumberOfEventsInAcquisition(12);

	d.maximumNumberOfEventsInSpill(32);          // TDC limit
	//d.maximumTimeOfSpill(UtlTimeDifference(0,60000)); // 60ms
	//d.maximumTimeOfSpill(UtlTimeDifference(0,40000)); // 40ms
	//d.maximumTimeOfSpill(UtlTimeDifference(0,100000)); // 100ms
	d.maximumTimeOfSpill(UtlTimeDifference(1));

	d.maximumTimeOfEvent(UtlTimeDifference(0,900000)); // 0.9s
	//d.maximumTimeOfEvent(UtlTimeDifference(1));
#endif

#ifdef NOT_DESY_SETTINGS
	//d.maximumNumberOfEventsInAcquisition(2000);

	d.maximumTimeOfConfiguration(UtlTimeDifference(15*60,0));

	//d.maximumNumberOfEventsInConfiguration(20000);
	d.maximumNumberOfEventsInSpill(2000);
	d.maximumTimeOfSpill(UtlTimeDifference(17)); // 17s
	d.maximumTimeOfEvent(UtlTimeDifference(100)); // 10s
#endif

      }
      break;
    }

    default: {
      // We missed a run type
      assert(false);
      break;
    }
    };
  }

  // Control for bursts called from DaqReadout
  static void numberOfTriggersInBurst(unsigned n) {
    _count[trgInRun]+=n;
    _count[trgInCfg]+=n;
    _count[trgInAcq]+=n;
  }

  static void maximumNumberOfExtraTriggersInBurst(unsigned m) {
    _maximumNumberOfExtraTriggersInBurst=m;
  }

  static void maximumTimeOfBurst(UtlTimeDifference d) {
    _maximumTimeOfBurst=d;
  }


protected:
  DaqRunStart _runStartFromRunControl;

private:
  static unsigned _count[endOfCounterEnum];
  static unsigned _maximumNumberOfExtraTriggersInBurst;
  static UtlTimeDifference _maximumTimeOfBurst;

  unsigned _runNumber;
  DaqConfigurationStart _daqConfigurationStart;

  /*
  ShmObject<RunControl> _shmRunControl;
  RunControl *_pRc;
  */
};

unsigned DaqConfiguration::_count[];
unsigned DaqConfiguration::_maximumNumberOfExtraTriggersInBurst=0;
UtlTimeDifference DaqConfiguration::_maximumTimeOfBurst(0x7fffffff,999999);

#endif
