#ifndef BmlCaen767Configuration_HH
#define BmlCaen767Configuration_HH

#include <iostream>
#include <fstream>

#include "RcdHeader.hh"
#include "RcdUserRW.hh"

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

#include "DaqRunType.hh"

#include "BmlCaen767ConfigurationData.hh"


class BmlCaen767Configuration : public RcdUserRW {

public:
  BmlCaen767Configuration(unsigned char c) :
    _location(c,0xffff,1),
    _controlRegister2(BmlCaen767OpcodeData().controlRegister2()) {
  }

  virtual ~BmlCaen767Configuration() {
  }

  virtual bool record(RcdRecord &r) {
    if(doPrint(r.recordType())) {
      std::cout << "BmlCaen767Configuration::record()" << std::endl;
      r.RcdHeader::print(std::cout," ") << std::endl;
    }
    
    // Check record type
    switch (r.recordType()) {
      
      // Run start 
    case RcdHeader::runStart: {

      // Access the DaqRunStart
      SubAccessor accessor(r);
      std::vector<const DaqRunStart*>
        v(accessor.access<DaqRunStart>());
      assert(v.size()==1);
      if(doPrint(r.recordType(),1)) v[0]->print(std::cout," ") << std::endl;

      _runType=v[0]->runType();

      break;
    }
      
      // Configuration start 
    case RcdHeader::configurationStart: {
      
      SubInserter inserter(r);
      BmlCaen767ReadoutConfigurationData rc;
      rc.crateNumber(_location.crateNumber());
      rc.bltReadout(false);
      rc.enable(false);

      // Handle the runs which need work
      if(_runType.majorType()==DaqRunType::bml ||
	 /*
	 _runType.majorType()==DaqRunType::beam ||

	 _runType.type()==DaqRunType::emcBeam ||
	 _runType.type()==DaqRunType::emcBeamHoldScan ||

	 _runType.type()==DaqRunType::ahcBeam ||
	 _runType.type()==DaqRunType::ahcBeamHoldScan ||
	 _runType.type()==DaqRunType::ahcBeamStage ||
	 _runType.type()==DaqRunType::ahcBeamStageScan) {
	 */
	 _runType.beamType()) {

	// Access the DaqConfigurationStart
	SubAccessor accessor(r);
	std::vector<const DaqConfigurationStart*>
	  v(accessor.access<DaqConfigurationStart>());
	assert(v.size()==1);
	if(doPrint(r.recordType(),1)) v[0]->print(std::cout," ") << std::endl;

	// Readout should be done for these runs
	rc.enable(true);
	rc.softTrigger(false);

	// Make a configuration object and set up control register 2
	// from the opcode default settings
	BmlLocationData<BmlCaen767ConfigurationData> cd(_location);
	//cd.label(1);
	cd.data()->controlRegister(1,_controlRegister2);

	//const unsigned char v(_runType.version());

	switch(_runType.type()) {

	case DaqRunType::bmlTest: {
	  rc.softTrigger(true);
	  break;
	}
      
	case DaqRunType::bmlNoise: {
	  rc.softTrigger(true);
	  break;
	}
      
	case DaqRunType::bmlInternalTest: {
	  cd.data()->memoryTest(true);
	  break;
	}
      
	case DaqRunType::bmlBeam:
      
	case DaqRunType::emcBeam:
	case DaqRunType::emcBeamHoldScan:

	case DaqRunType::sceBeam:
	case DaqRunType::sceBeamHoldScan:
	case DaqRunType::sceBeamStage:
	case DaqRunType::sceBeamStageScan:

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

	case DaqRunType::beamTest:
	case DaqRunType::beamNoise:
	case DaqRunType::beamData:
	case DaqRunType::beamHoldScan:
	case DaqRunType::beamStage:
	case DaqRunType::beamStageScan: {
	  if((v[0]->configurationNumberInRun()%3)==2) {

	  } else {
	    rc.enable(false);
	  }
	  break;
	}
	  
	default: {
	  break;
	}
	};
	
	// Put the configuration objects into the record
	inserter.insert< BmlLocationData<BmlCaen767ConfigurationData> >(cd);
	if(doPrint(r.recordType(),1)) cd.print(std::cout," ") << std::endl;
      }

      inserter.insert<BmlCaen767ReadoutConfigurationData>(rc);
      if(doPrint(r.recordType(),1)) rc.print(std::cout," ") << std::endl;

      break;
    }
      
      // Acquisition start 
    case RcdHeader::acquisitionStart: {
      
      switch(_runType.type()) {

      case DaqRunType::bmlInternalTest: {
	SubInserter inserter(r);

	BmlLocationData<BmlCaen767TestData>
	  *d(inserter.insert< BmlLocationData<BmlCaen767TestData> >(true));
	d->location(_location);
	d->data()->numberOfRepeats(16*1024);
	d->data()->setPattern(BmlCaen767TestData::empty);
	assert(inserter.extend(d->data()->numberOfWords()*4));

	break;
      }
	
      default: {
	break;
      }
      };
      
	  
      break;
    }
      
    default: {
      break;
    }
    };
    
    return true;
  }


private:
  DaqRunType _runType;
  const BmlLocation _location;
  const unsigned short _controlRegister2;
};

#endif
