#ifndef HstCrcSignal_HH
#define HstCrcSignal_HH

#include <cassert>

//#include "TROOT.h"
#include "TMapFile.h"
#include "TH1F.h"
#include "TH2F.h"
#include "TProfile.h"
#include "TRandom.h"

#include "DaqRunStart.hh"

#include "RcdUserRO.hh"
#include "RcdWriterDmy.hh"
#include "RcdWriterAsc.hh"
#include "RcdWriterBin.hh"

#include "UtlRollingAverage.hh"
#include "SubAccessor.hh"


class HstCrcSignal : public RcdUserRO {

public:
  HstCrcSignal() {
    _event[0]= new TH1F("HstCrcSignalCrate0","ECAL crate, event display",
			22*8*12*18,0,22*8*12*18);
    _event[1]= new TH1F("HstCrcSignalCrate1","AHCAL crate, event display",
			22*8*12*18,0,22*8*12*18);

    /*
    _signal[0]= new TH1F("HstCrcSignalCrate0Signal",
			 "ECAL crate, signal above pedestal",
			 200,-50,150);
    _signal[1]= new TH1F("HstCrcSignalCrate1Signal",
			"AHCAL crate, signal above pedestal",
			200,-500,1500);
    */
    for(unsigned i(0);i<7;i++) {
      std::string slot;
      if(i==0) slot="05";
      if(i==1) slot="07";
      if(i==2) slot="09";
      if(i==3) slot="12";
      if(i==4) slot="15";
      if(i==5) slot="17";
      if(i==6) slot="19";

      _signal[0][i]= new TH2F((std::string("HstCrcSignalCrate0Slot")+slot).c_str(),
			   "ECAL crate, signal above pedestal",
			   8*12*18,0,8*12*18,50,-50,150);
      
      _signal[1][i]= new TH2F((std::string("HstCrcSignalCrate1Slot")+slot).c_str(),
			   "AHCAL crate, signal above pedestal",
			   8*12*18,0,8*12*18,50,-500,1500);
    }

    for(unsigned i(0);i<=21;i++) _slots[i]=7;
    _slots[ 5]=0;
    _slots[ 7]=1;
    _slots[ 9]=2;
    _slots[12]=3;
    _slots[15]=4;
    _slots[17]=5;
    _slots[19]=6;
  }

  virtual ~HstCrcSignal() {
    delete _event[0];
    delete _event[1];
  }

  bool record(const RcdRecord &r) {
    //r.RcdHeader::print(std::cout);

    if(r.recordType()==RcdHeader::runStart) {

      SubAccessor accessor(r);

      std::vector<const DaqRunStart* >
	w(accessor.access<DaqRunStart>());

      if(w.size()>0) {
	if(doPrint(r.recordType(),1)) w[0]->print(std::cout," ") << std::endl;
	_runNumber.word(w[0]->runNumber());
      }

      if(_runNumber==0) _runNumber.word(999999);

      _cfgNumber.word(0);
      _acqNumber.word(0);
      _evtNumber.word(0);

      return true;
    }


    if(r.recordType()==RcdHeader::configurationStart) {

      SubAccessor accessor(r);

      _cfgNumber.word(_cfgNumber.word()+1);

      std::vector<const DaqConfigurationStart* >
	w(accessor.access<DaqConfigurationStart>());

      if(w.size()>0) {
	if(doPrint(r.recordType(),1)) w[0]->print(std::cout," ") << std::endl;
	_cfgNumber.word(w[0]->configurationNumberInRun());
      }

      for(unsigned i(0);i<2;i++) {
	for(unsigned j(0);j<22;j++) {
	  for(unsigned k(0);k<8;k++) {
	    for(unsigned l(0);l<12;l++) {
	      for(unsigned m(0);m<18;m++) {
		_pedestal[i][j][k][l][m].reset();
	      }
	    }
	  }
	}
      }

      return true;
    }


    if(r.recordType()==RcdHeader::acquisitionStart) {

      SubAccessor accessor(r);

      _acqNumber.word(_acqNumber.word()+1);

      std::vector<const DaqAcquisitionStart* >
	w(accessor.access<DaqAcquisitionStart>());

      if(w.size()>0) {
	if(doPrint(r.recordType(),1)) w[0]->print(std::cout," ") << std::endl;
	_acqNumber.word(w[0]->acquisitionNumberInRun());
      }

      return true;
    }


    if(r.recordType()==RcdHeader::event) {
      bool useForPedestal(true); // Make cleverer!

      // OK for Jan05 runs
      useForPedestal=((_cfgNumber.word()%2)==1);

      // Clear last event
      _event[0]->Reset();
      _event[1]->Reset();

      SubAccessor accessor(r);

      _evtNumber.word(_evtNumber.word()+1);

      std::vector<const DaqEvent* >
	w(accessor.access<DaqEvent>());

      if(w.size()>0) {
	_evtNumber.word(w[0]->eventNumberInRun());
	//	if(w[0]->eventNumberInAcquisition()==0) useForPedestal=false;
      }

      std::vector<const CrcLocationData<CrcVlinkEventData>* >
	v(accessor.access< CrcLocationData<CrcVlinkEventData> >());

      for(unsigned i(0);i<v.size();i++) {

	// Get crate number
	unsigned crate(2);
	if(v[i]->crateNumber()==0xec) crate=0;
	if(v[i]->crateNumber()==0xac) crate=1;
	if(crate<2) {
	  
	  // Get slot number
	  if(v[i]->slotNumber()<22) {
	    unsigned slot(v[i]->slotNumber());
	    if(_slots[slot]<7) {
	    
	      // Loop over FE number
	      for(unsigned fe(0);fe<8;fe++) {
		const CrcVlinkFeData *fd(v[i]->data()->feData(fe));
		if(fd!=0) {
		
		  // Loop over mplex channel number
		  for(unsigned chan(0);chan<v[i]->data()->feNumberOfAdcSamples(fe) && chan<18;chan++) {
		    const CrcVlinkAdcSample *as(fd->adcSample(chan));
		    if(as!=0) {
		    
		      // Loop over chips=ADCs
		      for(unsigned chip(0);chip<12;chip++) {
			
			// Plot this value above pedestal
			_event[crate]->Fill(8*12*18*slot+12*18*fe+18*chip+chan,
					    as->adc(chip)-_pedestal[crate][slot][fe][chip][chan].average());
			
			_signal[crate][_slots[slot]]->Fill(12*18*fe+18*chip+chan,
					     as->adc(chip)-_pedestal[crate][slot][fe][chip][chan].average());
			
			// Update pedestal
			if(useForPedestal) {
			  _pedestal[crate][slot][fe][chip][chan]+=as->adc(chip);
			}
		      }
		    }
		  }
		}
	      }
	    }
	  }
	}
      }

      // Label end of filling
      std::ostringstream sout;
      sout << r.recordTime();
      std::string rst(sout.str());

      for(unsigned i(0);i<2;i++) {

	// Add run/event numbers
	for(unsigned j(0);j<4;j++) {
	  _event[i]->Fill(j   ,0.5+(unsigned)_runNumber.byte(j));
	  _event[i]->Fill(j+ 4,0.5+(unsigned)_cfgNumber.byte(j));
	  _event[i]->Fill(j+ 8,0.5+(unsigned)_acqNumber.byte(j));
	  _event[i]->Fill(j+12,0.5+(unsigned)_evtNumber.byte(j));
	}

	// Also add event date and time as string
	_event[i]->Fill(16,0.5+rst.size());
	for(unsigned j(0);j<rst.size();j++) {
	  _event[i]->Fill(j+17,0.5+(unsigned)rst[j]);
	}
      }

      return true;
    }

    return true;
  }

private:
  UtlPack _runNumber;
  UtlPack _cfgNumber;
  UtlPack _acqNumber;
  UtlPack _evtNumber;

  unsigned _slots[22];
  TH1F *_event[2];
  TH2F *_signal[2][22];

  UtlAverage _pedestal[2][22][8][12][18];
};

#endif
