#ifndef HstEventRate_HH
#define HstEventRate_HH

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>

#include "TROOT.h"
#include "TApplication.h"
#include "TCanvas.h"
#include "TH1D.h"
#include "TH2D.h"
#include "TGraphErrors.h"
#include "TPostScript.h"

#include "UtlAverage.hh"
#include "RcdRecord.hh"
#include "CrcFeEventData.hh"
#include "CrcLocationData.hh"
#include "DaqEvent.hh"
#include "HstBase.hh"
#include "HstTGraphErrors.hh"
#include "SubAccessor.hh"


class HstEventRate : public HstBase {

public:
  HstEventRate(bool i=true, double w=300.0) : 
    HstBase(i), _timeBinWidth(w), _firstRecordTime(0), _timeBinEdge(0),
    _eventCount(0.0), _timeoutCount(0.0),
    _poll2d("poll2d","Poll number of tries vs time",100,0.0,0.2,100,0.0,1000.0),
    _poll1d("poll1d","Poll time",100,0.0,0.2) {

    _canvas[0]=new TCanvas("EventRateCanvas","Event rate",400,20,400,600);
    _canvas[0]->Divide(1,2);
    if(!interactive()) {
      _canvas[1]=new TCanvas("PollDataCanvas","Poll data",410,10,400,600);
      _canvas[1]->Divide(1,2);
    }
  }
  
  virtual ~HstEventRate() {
  }

  
  bool record(const RcdRecord &r) {

    if(r.recordType()==RcdHeader::runStart) _firstRecordTime=0;

    if(_firstRecordTime==0) {
      _firstRecordTime=r.recordTime().seconds();
      _graph.Set(0);
      _graph.SetTitle("Event rate / Hz against time since run start / min");
      _graph.SetMarkerColor(2);
      _graph.SetMarkerStyle(22);

      _gTout.Set(0);
      _gTout.SetTitle("Fraction of events with no trigger against time since run start / min");
      _gTout.SetMarkerColor(2);
      _gTout.SetMarkerStyle(22);
    }

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

      double deltat(r.recordTime().seconds()-_firstRecordTime);
    
      if((deltat-_timeBinEdge)>_timeBinWidth) {
	_graph.AddPoint((_timeBinEdge+0.5*_timeBinWidth)/60.0,
			_eventCount/_timeBinWidth,0.0,
			sqrt(_eventCount)/_timeBinWidth);

	if(_eventCount>0.0) {
	  double f(_timeoutCount/_eventCount);
	  _gTout.AddPoint(((_timeBinEdge+0.5*_timeBinWidth)/60.0),f,
			  0.0,sqrt(f*(1.0-f)/_eventCount));
	}

	if(interactive()) update();

	_eventCount=0.0;
	_timeoutCount=0.0;
	_timeBinEdge+=_timeBinWidth;
      }

      _eventCount++;

      SubAccessor accessor(r);
      std::vector<const CrcLocationData<CrcBeTrgPollData>*>
	v(accessor.extract<CrcLocationData<CrcBeTrgPollData> >());
      assert(v.size()==1);
      if(v[0]->data()->maximumTries()) _timeoutCount++;

      if(!interactive()) {
	double dt((r.recordTime()-v[0]->data()->time()).deltaTime());
	_poll2d.Fill(dt,v[0]->data()->numberOfTries());
	_poll1d.Fill(dt);
      }
    }

    return true;
  }

  
  bool update() {
    _canvas[0]->Clear("D");
    _canvas[0]->cd(1);
    _graph.Draw("AP");
    _canvas[0]->cd(2);
    _gTout.Draw("AP");
    _canvas[0]->Update();

    if(!interactive()) {
      _canvas[1]->Clear("D");
      _canvas[1]->cd(1);
      _poll2d.Draw("box");
      _canvas[1]->cd(2);
      _poll1d.Draw();
      _canvas[1]->Update();
    }

    return true;
  }

  bool postscript(std::string file) {
    std::cout << "HstEventRate::postscript()  Writing to file "
              << file << std::endl;

    TPostScript ps(file.c_str(),111);
    update();
    ps.Close();

    return true;
  }

private:
  double _timeBinWidth;
  unsigned _firstRecordTime;
  double _timeBinEdge;
  double _eventCount;
  double _timeoutCount;
  TCanvas *_canvas[2];
  HstTGraphErrors _graph;
  HstTGraphErrors _gTout;
  TH2D _poll2d;
  TH1D _poll1d;
};

#endif
