#ifndef HstHold_catherine_HH
#define HstHold_catherine_HH

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

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

#include "UtlAverage.hh"
#include "RcdRecord.hh"
#include "EmcEventEnergy.hh"
#include "CrcFeEventData.hh"
#include "CrcLocationData.hh"
#include "DaqEvent.hh"
#include "HstBase.hh"
#include "HstTGraph.hh"
#include "SubAccessor.hh"
#include "CrcBeTrgPollData.hh"

// fn to fit to pedestal and signal
Double_t DoubleG(Double_t *x, Double_t *par) {

  double mean0=par[2];
  double mean1=par[2]+par[0];
  double sigma0=par[0]/par[1];
  double sigma1=par[3];
  double norm0=par[4];
  double norm1=par[5];

  return norm0*exp(-0.5*(x[0]-mean0)*(x[0]-mean0)/(sigma0*sigma0))
        +norm1*exp(-0.5*(x[0]-mean1)*(x[0]-mean1)/(sigma1*sigma1));
}


// fn to fit to signal vs hold
Double_t crrc(Double_t *x, Double_t *par) {
  Double_t t=32.0;
  Double_t y=(x[0]-par[0])/t;
  if(y<-1.0) return 0.0;
  return par[1]*(y+1.0)*exp(-y);
}


// more general fn to fit to signal vs hold - don't fix time constant
Double_t crrc_gen(Double_t *x, Double_t *par) {
  Double_t y=(x[0]-par[0])/par[2];
  if(y<-1.0) return 0.0;
  return par[1]*(y+1.0)*exp(-y);
}


class HstHold_catherine : public HstBase {

public:
  HstHold_catherine(bool i=true) : 
    HstBase(i), _eventCount(0), _firstRecordTime(0), _Efirstlayer(0) {
    for(int i=0;i<28;i++){
      ostringstream sout;
      sout << "Hold";
      ostringstream sout2;
      sout2 << "Signal, hold = ";
      if(i<12){
	sout2 << i+1;
	sout << i+1;
      }
      else if(i==12) {
	sout2 << 14;
	sout << 14;
      }
      else if(i==13) {
	sout2 << 16;
	sout << 16;
      }
      else if(i==14) {
	sout2 << 18;
	sout << 18;
      }
      else if(i==15){
	sout2 << 20;
	sout << 20;
      }
      else if(i==16){
	sout2 << 25;
	sout << 25;
      }
      else if(i==17){
	sout2 << 30;
	sout << 30;
      }
      else if(i==18){
	sout2 << 35;
	sout << 35;
      }
      else if(i==19){
	sout2 << 40;
	sout << 40;
      }
      else if(i==20){
	sout2 << 50;
	sout << 50;
      }
      else if(i==21){
	sout2 << 60;
	sout << 60;
      }
      else if(i==22){
	sout2 << 80;
	sout << 80;
      }
      else if(i==23){
	sout2 << 100;
	sout << 100;
      }
      else if(i==24){
	sout2 << 150;
	sout << 150;
      }
      else if(i==25){
	sout2 << 200;
	sout << 200;
      }
      else if(i==26){
	sout2 << 250;
	sout << 250;
      }
      else if(i==27){
	sout2 << 300;
	sout << 300;
      }
      _hadc[i]=new TH1D(sout.str().c_str(),sout2.str().c_str(),100,-50,300);
      _canvas[i]=new TCanvas(sout.str().c_str(),"Hold studies - histograms",400,20,600,400);
    }
    ostringstream sout;
    sout << "HoldvsADC";
    _canvas[28]=new TCanvas(sout.str().c_str(),"Hold studies - graph",400,20,600,400); 
  }
  
  virtual ~HstHold_catherine() {
  }
  
  
  bool record(const RcdRecord &r) {
    return false;
  }


  bool record(const RcdRecord &r, const EmcEventEnergy en) {

    if(_firstRecordTime==0) {
      _firstRecordTime=r.recordTime().seconds();
      _graph.SetTitle("Average ADC count above pedestal vs. hold value");
      _graph.SetMarkerColor(2);
      _graph.SetMarkerStyle(22);

    }
    
    // put the filling the histograms bit here
    SubAccessor accessor(r);

    // get the hold value for each layer
    if(r.recordType()==RcdHeader::configurationStart) {
      std::vector<const CrcLocationData<EmcFeConfigurationData>*>
	vc(accessor.extract< CrcLocationData<EmcFeConfigurationData> >());      
      for(unsigned i(0);i<vc.size();i++) {
	if(vc[i]->slotNumber()==17 && vc[i]->crcComponent()==CrcLocation::fe6)
	  _hold[0]=vc[i]->data()->holdStart();
	if(vc[i]->slotNumber()==12 && vc[i]->crcComponent()==CrcLocation::fe1)
	  _hold[1]=vc[i]->data()->holdStart();
	if(vc[i]->slotNumber()==12 && vc[i]->crcComponent()==CrcLocation::fe2)
	  _hold[2]=vc[i]->data()->holdStart();
	if(vc[i]->slotNumber()==12 && vc[i]->crcComponent()==CrcLocation::fe3)
	  _hold[3]=vc[i]->data()->holdStart();
	if(vc[i]->slotNumber()==12 && vc[i]->crcComponent()==CrcLocation::fe4)
	  _hold[4]=vc[i]->data()->holdStart();
	if(vc[i]->slotNumber()==12 && vc[i]->crcComponent()==CrcLocation::fe5)
	  _hold[5]=vc[i]->data()->holdStart();
	if(vc[i]->slotNumber()==12 && vc[i]->crcComponent()==CrcLocation::fe6)
	  _hold[6]=vc[i]->data()->holdStart();
	if(vc[i]->slotNumber()==12 && vc[i]->crcComponent()==CrcLocation::fe7)
	  _hold[7]=vc[i]->data()->holdStart();
	if(vc[i]->slotNumber()==17 && vc[i]->crcComponent()==CrcLocation::fe0)
	  _hold[8]=vc[i]->data()->holdStart();
	if(vc[i]->slotNumber()==17 && vc[i]->crcComponent()==CrcLocation::fe1)
	  _hold[9]=vc[i]->data()->holdStart();
	if(vc[i]->slotNumber()==17 && vc[i]->crcComponent()==CrcLocation::fe2)
	  _hold[10]=vc[i]->data()->holdStart();
	if(vc[i]->slotNumber()==17 && vc[i]->crcComponent()==CrcLocation::fe3)
	  _hold[11]=vc[i]->data()->holdStart();
	if(vc[i]->slotNumber()==17 && vc[i]->crcComponent()==CrcLocation::fe4)
	  _hold[12]=vc[i]->data()->holdStart();
	if(vc[i]->slotNumber()==17 && vc[i]->crcComponent()==CrcLocation::fe5)
	  _hold[13]=vc[i]->data()->holdStart();
      }
      return true;
    }


    if(r.recordType()!=RcdHeader::event) return true;  // i.e. stop now if it's not an event
    
    // sum the energy of each pad of the first layer for the event
    for(unsigned x(0);x<18;x++) { 
      for(unsigned y(6);y<18;y++) { 
	if(en.energy(EmcPhysicalPad(x,y,0))>25.0) {   // choose cut above pedestal
	  _Efirstlayer+=en.energy(EmcPhysicalPad(x,y,0));
	}	  
      }
    }
 
    std::vector<const CrcLocationData<CrcBeTrgPollData>*> vto(accessor.extract< CrcLocationData<CrcBeTrgPollData> >());

    // if event didn't time out
    if(vto[0]->data()->maximumTries()){
      // if some energy was measured in the first layer
      if(_Efirstlayer!=0){
	if(_hold[0]==1) _hadc[0]->Fill(_Efirstlayer);
	if(_hold[0]==2) _hadc[1]->Fill(_Efirstlayer);
	if(_hold[0]==3) _hadc[2]->Fill(_Efirstlayer);
	if(_hold[0]==4) _hadc[3]->Fill(_Efirstlayer);
	if(_hold[0]==5) _hadc[4]->Fill(_Efirstlayer);
	if(_hold[0]==6) _hadc[5]->Fill(_Efirstlayer);
	if(_hold[0]==7) _hadc[6]->Fill(_Efirstlayer);
	if(_hold[0]==8) _hadc[7]->Fill(_Efirstlayer);
	if(_hold[0]==9) _hadc[8]->Fill(_Efirstlayer);
	if(_hold[0]==10) _hadc[9]->Fill(_Efirstlayer);
	if(_hold[0]==11) _hadc[10]->Fill(_Efirstlayer);
	if(_hold[0]==12) _hadc[11]->Fill(_Efirstlayer);
	if(_hold[0]==14) _hadc[12]->Fill(_Efirstlayer);
	if(_hold[0]==16) _hadc[13]->Fill(_Efirstlayer);
	if(_hold[0]==18) _hadc[14]->Fill(_Efirstlayer);
	if(_hold[0]==20) _hadc[15]->Fill(_Efirstlayer);
	if(_hold[0]==25) _hadc[16]->Fill(_Efirstlayer);
	if(_hold[0]==30) _hadc[17]->Fill(_Efirstlayer);
	if(_hold[0]==35) _hadc[18]->Fill(_Efirstlayer);
	if(_hold[0]==40) _hadc[19]->Fill(_Efirstlayer);
	if(_hold[0]==50) _hadc[20]->Fill(_Efirstlayer);
	if(_hold[0]==60) _hadc[21]->Fill(_Efirstlayer);
	if(_hold[0]==80) _hadc[22]->Fill(_Efirstlayer);
	if(_hold[0]==100) _hadc[23]->Fill(_Efirstlayer);
	if(_hold[0]==150) _hadc[24]->Fill(_Efirstlayer);
	if(_hold[0]==200) _hadc[25]->Fill(_Efirstlayer);
	if(_hold[0]==250) _hadc[26]->Fill(_Efirstlayer);
	if(_hold[0]==300) _hadc[27]->Fill(_Efirstlayer);
      }
    }

    _Efirstlayer=0;    
    
    return true;
  }
  
  
  bool update() {
    for(unsigned i=0;i<28;i++){
      _canvas[i]->Clear();
      _hadc[i]->Draw("hist");
      _canvas[i]->Update();
      if(i==0) _graph.AddPoint(1.0,_hadc[i]->GetMean());
      if(i==1) _graph.AddPoint(2.0,_hadc[i]->GetMean());
      if(i==2) _graph.AddPoint(3.0,_hadc[i]->GetMean());
      if(i==3) _graph.AddPoint(4.0,_hadc[i]->GetMean());
      if(i==4) _graph.AddPoint(5.0,_hadc[i]->GetMean());
      if(i==5) _graph.AddPoint(6.0,_hadc[i]->GetMean());
      if(i==6) _graph.AddPoint(7.0,_hadc[i]->GetMean());
      if(i==7) _graph.AddPoint(8.0,_hadc[i]->GetMean());
      if(i==8) _graph.AddPoint(9.0,_hadc[i]->GetMean());
      if(i==9) _graph.AddPoint(10.0,_hadc[i]->GetMean());
      if(i==10) _graph.AddPoint(11.0,_hadc[i]->GetMean());
      if(i==11) _graph.AddPoint(12.0,_hadc[i]->GetMean());
      if(i==12) _graph.AddPoint(14.0,_hadc[i]->GetMean());
      if(i==13) _graph.AddPoint(16.0,_hadc[i]->GetMean());
      if(i==14) _graph.AddPoint(18.0,_hadc[i]->GetMean());
      if(i==15) _graph.AddPoint(20.0,_hadc[i]->GetMean());
      if(i==16) _graph.AddPoint(25.0,_hadc[i]->GetMean());
      if(i==17) _graph.AddPoint(30.0,_hadc[i]->GetMean());
      if(i==18) _graph.AddPoint(35.0,_hadc[i]->GetMean());
      if(i==19) _graph.AddPoint(40.0,_hadc[i]->GetMean());
      if(i==20) _graph.AddPoint(50.0,_hadc[i]->GetMean());
      if(i==21) _graph.AddPoint(60.0,_hadc[i]->GetMean());
      if(i==22) _graph.AddPoint(80.0,_hadc[i]->GetMean());
      if(i==23) _graph.AddPoint(100.0,_hadc[i]->GetMean());
      if(i==24) _graph.AddPoint(150.0,_hadc[i]->GetMean());
      if(i==25) _graph.AddPoint(200.0,_hadc[i]->GetMean());
      if(i==26) _graph.AddPoint(250.0,_hadc[i]->GetMean());
      if(i==27) _graph.AddPoint(300.0,_hadc[i]->GetMean());

    }
    _canvas[28]->Clear();
    _graph.Draw("AP");
    _canvas[28]->Update();
    //   TF1 *fsighold = new TF1("sig_hold",crrc,0,100,2);
    //    fsighold->SetParameters(10.0,120.0);
    TF1 *fsighold = new TF1("sig_hold",crrc_gen,0,100,3);
    //    fsighold->SetParameters(10.0,120.0);
    fsighold->SetParameters(10.0,120.0,32.0);
    _graph.Fit("sig_hold","",0,0.0,100.0);
    _canvas[28]->Update();
    return true;
  }

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

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

    return true;
  }

private:
  double _eventCount;
  double _firstRecordTime;
  double _Efirstlayer;
  double _hold[14];  // value for each layer
  TCanvas *_canvas[29];  // one for each hold value + one for graph
  HstTGraph _graph;  // to plot average signal vs. hold value
  TH1 *_hadc[28];  // one for each hold value 
 
};

#endif
