//
// $Id: HstDhcQScan.hh,v 1.1 2008/06/27 10:34:01 meyern Exp $
//

#ifndef HstDhcQScan_HH
#define HstDhcQScan_HH

#include <iostream>
#include <sstream>
#include <map>
#include <vector>

#include "TROOT.h"
#include "TApplication.h"
#include "TCanvas.h"
#include "TGraphErrors.h"
#include "TMultiGraph.h"
#include "TH1D.h"
#include "TPostScript.h"
#include "TBrowser.h"

#include "UtlPack.hh"
#include "UtlAverage.hh"
#include "RcdRecord.hh"
#include "DaqEvent.hh"
#include "SubAccessor.hh"

const unsigned MAX_DCON = 12;
const unsigned MAX_CHIP = 4;
const unsigned MAX_CHAN = 64;


class HstDhcQScan {

public:
  HstDhcQScan(unsigned s, unsigned d=1)
    : _application("QinjScan Application",0,0),
      _slot(s), _dconMask(d)
  {
    gROOT->Reset();

    for(unsigned i(0);i<MAX_DCON;i++) {
      if (_dconMask.bit(i)) {
	std::ostringstream sout;
	sout << "Slot" << _slot <<  "-DCON" << i << "-QinjScan";

	_canvas[i]=new TCanvas(sout.str().c_str(),sout.str().c_str(),
			       40+20*i,40+20*i,900,500);
	_canvas[i]->Divide(3,2);

	_hist[i][0].SetNameTitle("Value", "Trigger Timestamp");
	_hist[i][0].SetBins(100, 0.0, 1000.);
	_hist[i][0].GetXaxis()->SetTitle("msec");
	_hist[i][1].SetNameTitle("Interval", "Trigger Timestamp");
	_hist[i][1].SetBins(100, 0.0, 100.);
	_hist[i][1].GetXaxis()->SetTitle("msec");
      }
    }
  }

  virtual ~HstDhcQScan() {
    std::map<unsigned, UtlAverage*>::iterator mit;
    for ( mit=_effMap.begin(); mit!=_effMap.end(); mit++ ) {
      delete [] (*mit).second;
    }
  }

  void update(bool ps=false) {

    double tLo = (*_effMap.begin()).first;
    double tHi = tLo;

    std::map<unsigned, UtlAverage*>::iterator mit = _effMap.begin();
    for ( unsigned bin(0); bin<_effMap.size(); bin++, mit++) {
      tHi = (*mit).first;
      UtlAverage *average = (*mit).second;
      
      for (unsigned d(0); d<MAX_DCON; d++) {
	if (_dconMask.bit(d)) {
	  for (unsigned a(0); a<MAX_CHIP; a++) {
	    for (unsigned c(0); c<MAX_CHAN; c++) {
	      _graph[d][a][c].SetPoint(bin,tHi,
				       average[d*MAX_CHIP*MAX_CHAN+a*MAX_CHAN+c].average());
	    }
	  }
	}
      }
    }

    for (unsigned d(0); d<MAX_DCON; d++) {
      if (_dconMask.bit(d)) {

	for (unsigned a(0); a<MAX_CHIP; a++) {
	  _canvas[d]->cd(3*(a/2)+a%2+1);

	  std::ostringstream sout;
	  sout << " Chip" << a;
	  _mgraph[d][a].SetTitle((sout.str()+" Efficiency vs Threshold").c_str());

	  for (unsigned c(0); c<MAX_CHAN; c++) {
	    _graph[d][a][c].SetLineColor(4);
	    _graph[d][a][c].SetMarkerColor(1);
	    _graph[d][a][c].SetMarkerStyle(6);
	    
	    _mgraph[d][a].Add(&_graph[d][a][c], "lp");
	  }
	  _mgraph[d][a].Draw("a");
	}

	_canvas[d]->cd(6)->SetLogy(1);
	_hist[d][0].Draw();
	_canvas[d]->cd(3)->SetLogy(1);
	_hist[d][1].Draw();
	_canvas[d]->Update();

	if (ps) {
	  std::ostringstream sout;
	  sout << "data/QinjScan" << d << ".ps";
	  _canvas[d]->Print(sout.str().c_str());
	}
      }
    }
    _application.Run(1);
  }

  void event(RcdRecord &r) {
    SubAccessor accessor(r);

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

    case RcdHeader::configurationStart: {
      std::vector<const DhcLocationData<DhcFeConfigurationData>*>
	fe(accessor.access< DhcLocationData<DhcFeConfigurationData> >());

      if (fe.size()>0) {
	_vtpd = *fe[0]->data()->vtpd();
	_injMask.word(*fe[0]->data()->inj());

	if (_effMap.find(_vtpd) == _effMap.end()) {
	  _effMap[_vtpd] = new UtlAverage[MAX_DCON*MAX_CHIP*MAX_CHAN];
	}
      }
      // reset timestamp
      _tslast=0;
      break;
    }

    case RcdHeader::event: {
      std::vector<const DhcLocationData<DhcEventData>*>
	v(accessor.access<DhcLocationData<DhcEventData> >());
      
      if (v[0]->slotNumber() == _slot) {
	for (unsigned d(0); d<MAX_DCON; d++) {
	  if (_dconMask.bit(d)) {

	    for (unsigned i(0); i<v[0]->data()->numberOfWords()/4; i++) {
	      const DhcFeHitData* hits(v[0]->data()->feData(i));
	      if (hits->dcolad() == d) {
		if (hits->trg()) {
		  double timestamp = hits->timestamp();
		  _hist[d][0].Fill(timestamp/10000.);
		  if (_tslast > 0 ) {
		    double elapse = timestamp > _tslast ?
		      timestamp - _tslast :
		      timestamp + 10000000 - _tslast;
		    _hist[d][1].Fill(elapse/10000.);
		  }		  
		  _tslast = timestamp;
		}
		else {
		  UtlPack hitsHi(hits->hitsHi());
		  UtlPack hitsLo(hits->hitsLo());
		  unsigned a(hits->dcalad());
		  for (unsigned c(0); c<MAX_CHAN; c++) {
		    if (_injMask.bit(c%4)) {
		      double hit = c<32 ?
			(hitsLo.bit(c%32) ? 1.0 : 0.0) :
			(hitsHi.bit(c%32) ? 1.0 : 0.0);

		      UtlAverage *average = _effMap[_vtpd];
		      average[d*MAX_CHIP*MAX_CHAN+a*MAX_CHAN+c].event(hit);
		    }
		  }
		}
	      }
	    }
	  }
	}
      }
      break;
    }

    default: {
      break;
    }
    };
  }

private:
  TApplication _application;

  const unsigned _slot;
  UtlPack _dconMask;
  UtlPack _injMask;

  std::map<unsigned, UtlAverage*> _effMap;
  unsigned _vtpd;
  double _tslast;

  TCanvas *_canvas[MAX_DCON];
  TMultiGraph _mgraph[MAX_DCON][MAX_CHIP];
  TGraphErrors _graph[MAX_DCON][MAX_CHIP][MAX_CHAN];
  TH1D _hist[MAX_DCON][2];

};

#endif // HstDhcQScan_HH
