#ifndef HstBeTrgHistoryMap_HH
#define HstBeTrgHistoryMap_HH

#include <cassert>

#include "TH2F.h"
#include "TH1F.h"
#include "TCanvas.h"

#include "RcdUserRO.hh"
#include "SubAccessor.hh"


class HstBeTrgHistoryMap : public RcdUserRO {

public:

  HstBeTrgHistoryMap() {
    _hTitle1=" History of Trigger Bits; Word; Bit";
    _hTitle2=" Number of Objects";
    _hTitle3=" Number of Errors";

    _history1=new TH2F("HstBeTrgHistoryMap1",(std::string("Total")+_hTitle1).c_str(),
		      256,0,256,32,0,32);
    _history2=new TH2F("HstBeTrgHistoryMap2",(std::string("Run")+_hTitle1).c_str(),
		      256,0,256,32,0,32);
    _history3=new TH2F("HstBeTrgHistoryMap3",(std::string("Configuration")+_hTitle1).c_str(),
    		      256,0,256,32,0,32);
    _history1a=new TH1F("HstBeTrgHistoryMap1a",(std::string("Total")+_hTitle2).c_str(),10,0,10);
    _history1b=new TH1F("HstBeTrgHistoryMap1b",(std::string("Total")+_hTitle3).c_str(),10,0,10);
    _history2a=new TH1F("HstBeTrgHistoryMap2a",(std::string("Run")+_hTitle2).c_str(),10,0,10);
    _history2b=new TH1F("HstBeTrgHistoryMap2b",(std::string("Run")+_hTitle3).c_str(),10,0,10);
    _history3a=new TH1F("HstBeTrgHistoryMap3a",(std::string("Configuration")+_hTitle2).c_str(),10,0,10);
    _history3b=new TH1F("HstBeTrgHistoryMap3b",(std::string("Configuration")+_hTitle3).c_str(),10,0,10);

  }


  virtual ~HstBeTrgHistoryMap() {
    delete _history1;
    _history1=0;
    delete _history2;
    _history2=0;
    delete _history3;
    _history3=0;
    delete _history1a;
    _history1a=0;
    delete _history1b;
    _history1b=0;
    delete _history2a;
    _history2a=0;
    delete _history2b;
    _history2b=0;
    delete _history3a;
    _history3a=0;
    delete _history3b;
    _history3b=0;

  }

  bool record(const RcdRecord &r) {

    if(r.recordType()==RcdHeader::runStart) {
      
      SubAccessor accessor(r);
      std::vector<const DaqRunStart*>
	v(accessor.access<DaqRunStart>());

      _runnum=999999;
      if(v.size()>0) _runnum=v[0]->runNumber();

      std::ostringstream sout;
      sout << "Run " << _runnum;
      _history2->SetTitle((sout.str()+_hTitle1).c_str());
      _history2a->SetTitle((sout.str()+_hTitle2).c_str());
      _history2b->SetTitle((sout.str()+_hTitle3).c_str());

      //std::cout << "Title set to " << _history2->GetTitle() << std::endl;

      _history2->Reset();
      _history2a->Reset();
      _history2b->Reset();
      return true;
    }
    
    if(r.recordType()==RcdHeader::configurationStart) {

      SubAccessor accessor(r);
      std::vector<const DaqConfigurationStart*>
	v(accessor.access<DaqConfigurationStart>());
      
      _connum=999999;
      if(v.size()>0) _connum=v[0]->configurationNumberInRun();
      
      std::ostringstream sout;
      sout << "Run " << _runnum << ", Configuration " << _connum;
      _history3->SetTitle((sout.str()+_hTitle1).c_str());
      _history3a->SetTitle((sout.str()+_hTitle2).c_str());
      _history3b->SetTitle((sout.str()+_hTitle3).c_str());

      //std::cout << "Title set to " << _history3->GetTitle() << std::endl;

      _history3->Reset();
      _history3a->Reset();
      _history3b->Reset();
      return true;
    }

    if(r.recordType()==RcdHeader::trigger) {
      //r.RcdHeader::print(std::cout);

      SubAccessor accessor(r);
      std::vector<const CrcLocationData<CrcBeTrgEventData>* >
	v(accessor.access< CrcLocationData<CrcBeTrgEventData> >());

      _history1a->Fill(v.size());
      _history2a->Fill(v.size());
      _history3a->Fill(v.size());
      
      for(unsigned i(0);i<v.size();i++) {
	//v[i]->print(std::cout);

	if(v[i]->data()->numberOfFifoWords()>0) {

	  if(_history1!=0) {
	    const unsigned *p=v[i]->data()->fifoData();
	    if(p[0]!=0x12345678) {
	      std::cout << "p[0] = " << printHex(p[0]) << std::endl;
	      _history1b->Fill(0.5);
	      _history2b->Fill(0.5);
	      _history3b->Fill(0.5);
	    }
	    if(p[v[i]->data()->numberOfFifoWords()-1]!=0xfedcba98) {
	      std::cout << "p[255] = " << printHex(p[v[i]->data()->numberOfFifoWords()-1]) << std::endl;
	      _history1b->Fill(1.5);
	      _history2b->Fill(1.5);
	      _history3b->Fill(1.5);
	    }
	    
	    for(unsigned j(2);j<v[i]->data()->numberOfFifoWords()-1;j++) {
	      for(unsigned k(0);k<32;k++) {
		if((p[j]&(1<<k))!=0) _history1->Fill(j,k);
		if((p[j]&(1<<k))!=0) _history2->Fill(j,k);
		if((p[j]&(1<<k))!=0) _history3->Fill(j,k); 
	      }
	    }
	  }

	  // No data words
	} else {
	  _history1b->Fill(2.5);
	  _history2b->Fill(2.5);
	  _history3b->Fill(2.5);
	}
      }
      return true;
    }

    if(r.recordType()==RcdHeader::event) {
      if((_connum%3)==0) {
	SubAccessor accessor(r);
	std::vector<const CrcLocationData<CrcVlinkEventData>* >
	  v(accessor.access< CrcLocationData<CrcVlinkEventData> >());
	
	for(unsigned i(0);i<v.size();i++) {
	  const CrcVlinkTrgData *td(v[i]->data()->trgData());
	  if(td!=0) {
	    if(td->header()!=0x12345678) {
	      std::cout << "p[0] = " << printHex(td->header()) << std::endl;
	      _history1b->Fill(0.5);
	      _history2b->Fill(0.5);
	      _history3b->Fill(0.5);
	    }
	    if(td->trailer(256)!=0xfedcba98) {
	      std::cout << "p[255] = " << printHex(td->trailer(256)) << std::endl;
	      _history1b->Fill(1.5);
	      _history2b->Fill(1.5);
	      _history3b->Fill(1.5);
	    }
	    
	    const unsigned *p=td->data();
	    for(unsigned j(0);j<253;j++) {
	      for(unsigned k(0);k<32;k++) {
		if((p[j]&(1<<k))!=0) _history1->Fill(j,k);
		if((p[j]&(1<<k))!=0) _history2->Fill(j,k);
		if((p[j]&(1<<k))!=0) _history3->Fill(j,k); 
	      }
	    }
	  }
	}
      }
    }

    return true;
   }
  
private:
  TH2F *_history1;
  TH2F *_history2;
  TH2F *_history3;
  TH1F *_history1a;
  TH1F *_history1b;
  TH1F *_history2a;
  TH1F *_history2b;
  TH1F *_history3a;
  TH1F *_history3b;

  unsigned _runnum;
  unsigned _connum;
  std::string _hTitle1;
  std::string _hTitle2;
  std::string _hTitle3;
};

#endif
