#ifndef HstTriggerPoll_HH
#define HstTriggerPoll_HH

#include <cassert>

#include "TMapFile.h"
#include "TH1F.h"

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


class HstTriggerPoll : public RcdUserRO {

public:
  HstTriggerPoll() {

    _hstTrgEventJobTime=new TH1F("HstTriggerSPollJobTime",
				 "Spill poll time in job (secs)",
				 100,0,0.2);
    _hstTrgEventRunTime=new TH1F("HstTriggerSPollRunTime",
				 "Spill poll time in run (secs)",
				 100,0,0.2);
    _hstTrgEventJobTriggers=new TH1F("HstTriggerSPollJobTriggers",
				     "Number of triggers per spill in job",
				     100,0,1000);
    _hstTrgEventRunTriggers=new TH1F("HstTriggerSPollRunTriggers",
				     "Number of triggers per spill in run",
				     100,0,1000);
    _hstTrgEventJobPolls=new TH1F("HstTriggerSPollJobPolls",
				  "Number of polls per spill in job",
				  100,0,10000);
    _hstTrgEventRunPolls=new TH1F("HstTriggerSPollRunPolls",
				  "Number of polls per spill in run",
				  100,0,10000);

    _trgPoll[0][0]=new TH1F("HstTriggerPollJobShort",
			 "Poll time in job;Seconds;Number of events",
			    100,0,0.01);
    _trgPoll[1][0]=new TH1F("HstTriggerPollJobLong",
			 "Poll time in job;Seconds;Number of events",
			 100,0,1.0);

    _trgPoll[0][1]=new TH1F("HstTriggerPollRunShort",
			 "Poll time in run;Seconds;Number of events",
			  100,0,0.01);
    _trgPoll[1][1]=new TH1F("HstTriggerPollRunLong",
			 "Poll time in run;Seconds;Number of events",
			 100,0,1.0);

    _trgPoll[0][2]=new TH1F("HstTriggerPollCfgShort",
			 "Poll time in configuration;Seconds;Number of events",
			  100,0,0.01);
    _trgPoll[1][2]=new TH1F("HstTriggerPollCfgLong",
			 "Poll time in configuration;Seconds;Number of events",
			 100,0,1.0);

    _trgProc[0][0]=new TH1F("HstTriggerProcJobShort",
			 "Process time in job;Seconds;Number of events",
			  100,0,0.01);
    _trgProc[1][0]=new TH1F("HstTriggerProcJobLong",
			 "Process time in job;Seconds;Number of events",
			 100,0,1.0);

    _trgProc[0][1]=new TH1F("HstTriggerProcRunShort",
			 "Process time in run;Seconds;Number of events",
			  100,0,0.01);
    _trgProc[1][1]=new TH1F("HstTriggerProcRunLong",
			 "Process time in run;Seconds;Number of events",
			 100,0,1.0);

    _trgProc[0][2]=new TH1F("HstTriggerProcCfgShort",
			 "Process time in configuration;Seconds;Number of events",
			  100,0,0.01);
    _trgProc[1][2]=new TH1F("HstTriggerProcCfgLong",
			 "Process time in configuration;Seconds;Number of events",
			 100,0,1.0);

    _triggerRecord=false;
  }

  virtual ~HstTriggerPoll() {
    delete _hstTrgEventJobTime;
    delete _hstTrgEventRunTime;
    delete _hstTrgEventJobTriggers;
    delete _hstTrgEventRunTriggers;
    delete _hstTrgEventJobPolls;
    delete _hstTrgEventRunPolls;
  }

  /*
  void update() {
    _hstTrgEventJobBytes.Draw();
  }
  */
  /*
  void extend(TH1F *hst, unsigned extraBins) {
    double *c(new double[hst->GetNbinsX()]);

    for(int i(0);i<hst->GetNbinsX();i++) {
      c[i]=hst->GetBinContent(i+1);
    }

    const TAxis *axis(hst->GetXaxis());

    std::cout << "Extending from " << hst->GetNbinsX() << " bins, x range "
	      << axis->GetXmin() << " - " << axis->GetXmax() << " to " 
	      << hst->GetNbinsX()+extraBins << " bins, x range "
	      << axis->GetXmin() << " - "
	      << axis->GetXmax()+extraBins*hst->GetBinWidth(1) << std::endl;

    int oldBins(hst->GetNbinsX());
    hst->SetBins(hst->GetNbinsX()+extraBins,
		 axis->GetXmin(),
		 axis->GetXmax()+extraBins*hst->GetBinWidth(1));

    for(int i(0);i<oldBins;i++) {
      hst->SetBinContent(i+1,c[i]);
    }

    delete [] c;
  }
  */

  bool record(const RcdRecord &r) {
    /*
    if(_startJob.seconds()==0) {
      _startJob=r.recordTime();
      _startRun=r.recordTime();
    }
    */
    if(_triggerRecord) {
      _triggerRecord=false;

      double pt((r.recordTime()-_lastTrigger).deltaTime()-_lastPoll);
      for(unsigned i(0);i<3;i++) {
	_trgProc[0][i]->Fill(pt);
	_trgProc[1][i]->Fill(pt);
      }
    }

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

      // Reset all run hists
      _hstTrgEventRunTime->Reset();
      _hstTrgEventRunTriggers->Reset();
      _hstTrgEventRunPolls->Reset();

      _trgPoll[0][1]->Reset();
      _trgPoll[1][1]->Reset();
      _trgProc[0][1]->Reset();
      _trgProc[1][1]->Reset();
      return true;
    }



    if(r.recordType()==RcdHeader::configurationStart) {
      _trgPoll[0][2]->Reset();
      _trgPoll[1][2]->Reset();
      _trgProc[0][2]->Reset();
      _trgProc[1][2]->Reset();
      return true;
    }

    /*
    if(r.recordType()==RcdHeader::spill) {
      SubAccessor accessor(r);
      std::vector<const CrcLocationData<TrgSpillPollData>* >
        v(accessor.access< CrcLocationData<TrgSpillPollData> >());

      if(v.size()>0) {
	v[0]->print(std::cout,"HstTriggerPoll  ");

	_hstTrgEventJobTime->Fill(v[0]->data()->actualPollTime().deltaTime());
	_hstTrgEventRunTime->Fill(v[0]->data()->actualPollTime().deltaTime());
	_hstTrgEventJobTriggers->Fill(v[0]->data()->actualNumberOfEvents());
	_hstTrgEventRunTriggers->Fill(v[0]->data()->actualNumberOfEvents());
	_hstTrgEventJobPolls->Fill(v[0]->data()->numberOfPolls());
	_hstTrgEventRunPolls->Fill(v[0]->data()->numberOfPolls());
      }
      return true;
    }
    */

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

      if(v.size()>0) {
	_triggerRecord=true;
	_lastTrigger=r.recordTime();
	_lastPoll=v[0]->data()->actualTime().deltaTime();

	for(unsigned i(0);i<3;i++) {
	  _trgPoll[0][i]->Fill(_lastPoll);
	  _trgPoll[1][i]->Fill(_lastPoll);
	}
      }
      return true;
    }


    return true;
  }

private:
  TH1F *_hstTrgEventJobTime;
  TH1F *_hstTrgEventRunTime;
  TH1F *_hstTrgEventJobTriggers;
  TH1F *_hstTrgEventRunTriggers;
  TH1F *_hstTrgEventJobPolls;
  TH1F *_hstTrgEventRunPolls;

  bool _triggerRecord;
  UtlTime _lastTrigger;
  double _lastPoll;

  TH1F *_trgPoll[2][3];
  TH1F *_trgProc[2][3];
};

#endif
