#ifndef MpsAnalysisPmtThresholdScan_HH
#define MpsAnalysisPmtThresholdScan_HH

#include <cassert>

#include "TFile.h"
#include "TF1.h"
#include "TH1F.h"
#include "TH2F.h"
#include "TProfile.h"

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

#include "MpsAnalysisBase.hh"
#include "MpsSensor1HitLists.hh"


class MpsAnalysisPmtThresholdScan : public MpsAnalysisBase {

public:
  MpsAnalysisPmtThresholdScan() : MpsAnalysisBase("MpsAnalysisPmtThresholdScan") {
  }

  virtual ~MpsAnalysisPmtThresholdScan() {
    endRoot();
  }

  virtual bool mpsAnalysisValidRun(IlcRunType::Type t) const {
    return t==IlcRunType::usbPmtThresholdScan;
  }

  bool runStart(const RcdRecord &r) {
    for(unsigned i(0);i<2;i++) {
      std::ostringstream slab;
      slab << "Pmt" << i;

      std::ostringstream stit;
      stit << _runTitle << ", PMT " << i;

      _hNRun[i]=new TH2F((slab.str()+"HNRun").c_str(),
			 (stit.str()+", Number of tags vs threshold").c_str(),
			 256,0.0,256.0,100,0.0,100.0);
      _pNRun[i]=new TProfile((slab.str()+"PNRun").c_str(),
			     (stit.str()+", Number of tags vs threshold").c_str(),
			     256,0.0,256.0);
      _hDRun[i]=new TH1F((slab.str()+"HDRun").c_str(),
			 (stit.str()+", Differential of tags vs threshold").c_str(),
			 256,0.0,256.0);
    }
    return true;
  }

  bool configurationStart(const RcdRecord &r) {
    for(unsigned s(0);s<_vLocation.size();s++) {
      if(_vLocation[s].usbDaqMaster()) {
	for(unsigned i(0);i<2;i++) {
	  std::ostringstream slab;
	  slab << _cfgLabel << "PMT" << i;
	  
	  std::ostringstream stit;
	  stit << _cfgTitle << ", PMT " << i << ", Threshold "
	       << _vUsbDaqConfigurationData[s].discriminatorThreshold(i);

	  _dt[i]=_vUsbDaqConfigurationData[s].discriminatorThreshold(i);
      
	  _hNumb[i]=new TH1F((slab.str()+"Numb").c_str(),
			     (stit.str()+", Number of tags").c_str(),
			     100,0.0,100.0);
	  _hTime[i]=new TH1F((slab.str()+"Time").c_str(),
			     (stit.str()+", Time of tags").c_str(),
			     8200,0.0,8200.0);
	}
      }
    }
    return true;
  }
  
  bool bunchTrain(const RcdRecord &r) {
    SubAccessor accessor(r);

    std::vector<const MpsLocationData<MpsUsbDaqBunchTrainData>* >
      w(accessor.access< MpsLocationData<MpsUsbDaqBunchTrainData> >());
    //assert(w.size()==1);
    
    unsigned numb[2]={0,0};
    for(unsigned s(0);s<w.size();s++) {
      if(doPrint(r.recordType(),1)) w[s]->print(std::cout) << std::endl;
      if(w[s]->usbDaqMaster()) {
	const MpsUsbDaqBunchTrainDatum *q(w[s]->data()->data());
	for(unsigned k(0);k<w[s]->data()->numberOfTags();k++) {
	  for(unsigned i(0);i<2;i++) {
	    if(q[k].channel(i)) {
	      numb[i]++;
	      _hTime[i]->Fill(q[k].timeStamp());
	    }
	  }
	}
	
	for(unsigned i(0);i<2;i++) {
	  _hNRun[i]->Fill(_dt[i],numb[i]);
	  _pNRun[i]->Fill(_dt[i],numb[i]);
	  _hNumb[i]->Fill(numb[i]);
	}
      }
    }

    return true;
  }

  void endRoot() {
    if(_rootFile!=0) {
      for(unsigned i(1);i<255;i++) {
	for(unsigned j(0);j<2;j++) {
	  double cont(0.5*(_pNRun[j]->GetBinContent(i+2)-_pNRun[j]->GetBinContent(i)));
	  double cerr(0.5*std::sqrt(_pNRun[j]->GetBinError(i+2)*_pNRun[j]->GetBinError(i+2)
				    +_pNRun[j]->GetBinError(i)*_pNRun[j]->GetBinError(i)));
	  _hDRun[j]->SetBinContent(i+1,cont);
	  _hDRun[j]->SetBinError(i+1,cerr);
	}
      }



      MpsAnalysisBase::endRoot();
    }
  }



private:
  unsigned _dt[2];

  TH2F     *_hNRun[2];
  TProfile *_pNRun[2];
  TH1F *_hDRun[2];

  TH1F *_hNumb[2];
  TH1F *_hTime[2];
};

#endif
