#ifndef AhcConfiguration_HH
#define AhcConfiguration_HH

#include <iostream>
#include <fstream>

// dual/inc/rcd
#include "RcdHeader.hh"
#include "RcdUserRW.hh"

// dual/inc/sub
#include "SubInserter.hh"
#include "SubAccessor.hh"
//#include "SubModifier.hh"

// online/inc/crc
#include "CrcConfiguration.hh"
//#include "CrcReadoutStartupData.hh"
#include "CrcReadoutConfigurationData.hh"


class AhcConfiguration : public CrcConfiguration {

public:
  AhcConfiguration() : CrcConfiguration(0xac), _tcmLocation(0xac,0,0,1) {
  }

  virtual ~AhcConfiguration() {
  }

  void tcmSlot(unsigned s) {
    assert(s>0 && s<=21);
    _tcmLocation.slotNumber(s);
 
    std::cout << "AhcConfiguration::tcmSlot()" << std::endl;
    _tcmLocation.print(std::cout," ") << std::endl;
  }

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

    // Do underlying CRC configuration
    assert(CrcConfiguration::record(r));

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

    // Run start 
    case RcdHeader::startUp: {
      assert(startUpConfiguration(r));
      break;
    }

    // Configuration start 
    case RcdHeader::configurationStart: {

     // Handle the ones which need work
      if(_runType.majorType()==DaqRunType::ahc  ||
	 _runType.majorType()==DaqRunType::beam ||
	 _runType.majorType()==DaqRunType::cosmics) {
	ahcReadoutConfiguration(r);
	ahcBeConfiguration(r);
	vfeConfiguration(r);
	ahcFeConfiguration(r);
      }

      break;
    }

    default: {
      break;
    }
    };

    return true;
  }


  virtual bool startUpConfiguration(RcdRecord &r) {

    // Load DAC values here

    // Save enables here
    for(unsigned i(2);i<=21;i++) _readoutConfiguration.slotEnable(i,false);

    _readoutConfiguration.crateNumber(0xac);
    _readoutConfiguration.slotEnable(12,true);
    _readoutConfiguration.slotFeEnable(12,1,true); // Slot 12 FE 1
    if(doPrint(r.recordType(),1)) _readoutConfiguration.print(std::cout," ");

    return true;
  }


  virtual bool ahcReadoutConfiguration(RcdRecord &r) {

      SubAccessor modifier(r);

      std::vector<const CrcReadoutConfigurationData*> v(modifier.access<CrcReadoutConfigurationData>());
      assert(v.size()==1);
      
      CrcReadoutConfigurationData *w((CrcReadoutConfigurationData*)v[0]);
      w->crateNumber(_location.crateNumber());
      for(unsigned i(2);i<=21;i++) {
	w->slotEnable(i,false);
      }

    return true;
  }


  virtual bool ahcBeConfiguration(RcdRecord &r) {

    return true;
  }

  virtual bool ahcFeConfiguration(RcdRecord &r) {
    SubInserter inserter(r);

    CrcLocationData<CrcFeConfigurationData>
      *d(inserter.insert< CrcLocationData<CrcFeConfigurationData> >(true));
    d->crateNumber(_location.crateNumber());
    d->slotBroadcast(true);
    d->crcComponent(CrcLocation::feBroadcast);
    d->label(1);

    unsigned nadc=18;
    d->data()->adcStartBeforeClock(5);
    d->data()->adcEndAfterClock(5);

    d->data()->holdStart(1);
    d->data()->holdWidth(nadc*4*700);
    d->data()->vfeMplexClockPulses(nadc);

    AhcVfeControl c(0);
    //c.swHoldIn(true);
    //c.ledSel(true);
    d->data()->vfeControl(c.data());

    if(_printLevel>2) d->print(std::cout) << std::endl;

    return true;
  }

  virtual bool vfeConfiguration(RcdRecord &r) {
    SubInserter inserter(r);

    for(unsigned f(1);f<2;f++) {
      CrcLocationData<AhcVfeConfigurationData>
	*d(inserter.insert< CrcLocationData<AhcVfeConfigurationData> >(true));
      d->crateNumber(_location.crateNumber());
      d->slotBroadcast(true);
      d->crcComponent((CrcLocation::CrcComponent)f);
      d->label(1);
      
      if(_printLevel>3) d->print(std::cout) << std::endl;
    }

    return true;
  }

protected:
  CrcLocation _tcmLocation;
  CrcReadoutConfigurationData _readoutConfiguration;
};

#endif
