#ifndef MpsAnalysisLaserTimeScan_HH
#define MpsAnalysisLaserTimeScan_HH

#include <cassert>

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

#include "HstCfgScan.hh"
#include "MpsSensor1BunchTrainData.hh"


class MpsAnalysisLaserTimeScan : public MpsAnalysisBase {

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

  virtual ~MpsAnalysisLaserTimeScan() {
    if(_rootFile!=0) {
      _rootFile->cd();

      endRun();
      /*
      for(unsigned s(0);s<_vLocation.size();s++) {
	for(unsigned i(0);i<4;i++) {
	  _regionWords[s][i]->runEnd();
	  _regionLogWs[s][i]->runEnd();
	}
      } 
      */
    }
  }

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

  void bookHist(unsigned x, unsigned y) {
    std::ostringstream sLabel;
    sLabel << _sensorLabel[0] << "X"
	   << std::setw(3) << std::setfill('0') << x << "Y"
	   << std::setw(3) << std::setfill('0') << y;
    
    std::ostringstream sTitle;
    sTitle << _runTitle << ", " << _sensorTitle[0]
	   << ", X " << x << ", Y " << y;

    _hHits[x][y]=new TH2F((sLabel.str()+"2D").c_str(),
			  (sTitle.str()+", Timestamp vs. trigger time").c_str(),
			  //50,80,130,12,0,12);
			  40,7020,7060,20,0,20);
    _hHit1[x][y]=new TH1F((sLabel.str()+"1D").c_str(),
			  (sTitle.str()+", Trigger time of hits").c_str(),
			  //50,80,130);
			  40,7020,7060);

  }

  bool runStart(const RcdRecord &r) {
    for(unsigned x(0);x<168;x++) {
      for(unsigned y(0);y<168;y++) {
	_hHits[x][y]=0;
	_hHit1[x][y]=0;
      }
    }

    return true;
  }

  void endRun() {
  /*
    if(_rootFile!=0) {
      //TF1 line("line","pol1",0,100000);
      TF1 line("gaus","gaus",-100000,100000);
      //_hMonoSummary=new TH1F("hMonoSummary","Summary",168*168,0.0,168.0*168.0);
      
      _hRawMean=new TH1F("hRawMean","Raw mean summary",500,_loLimit,_hiLimit);
      _hRawRms=new TH1F("hRawRms","Raw RMS summary",100,0.0,100.0);

      _hSummaryNorm=new TH1F("hSummaryNorm","Norm summary",100,0.0,100000.0);
      _hSummaryMean=new TH1F("hSummaryMean","Mean summary",500,_loLimit,_hiLimit);
      _hSummaryRms=new TH1F("hSummaryRms","RMS summary",100,0.0,100.0);

      _hPixelSummaryNorm=new TH1F("hPixelSummaryNorm","Pixel Norm summary",168*168,0.0,168.0*168.0);
      _hPixelSummaryMean=new TH1F("hPixelSummaryMean","Pixel Mean summary",168*168,0.0,168.0*168.0);
      _hPixelSummaryRms=new TH1F("hPixelSummaryRms","Pixel RMS summary",168*168,0.0,168.0*168.0);

      _hQuadRawMean[0]=new TH1F("hRawMean0","Quad0, Raw mean summary",500,_loLimit,_hiLimit);
      _hQuadRawRms[0]=new TH1F("hRawRms0","Quad0, Raw RMS summary",100,0.0,100.0);
      _hQuadRawMean[1]=new TH1F("hRawMean1","Quad1, Raw mean summary",500,_loLimit,_hiLimit);
      _hQuadRawRms[1]=new TH1F("hRawRms1","Quad1, Raw RMS summary",100,0.0,100.0);
      _hQuadRawMean[2]=new TH1F("hRawMean2","Quad2, Raw mean summary",500,_loLimit,_hiLimit);
      _hQuadRawRms[2]=new TH1F("hRawRms2","Quad2, Raw RMS summary",100,0.0,100.0);
      _hQuadRawMean[3]=new TH1F("hRawMean3","Quad3, Raw mean summary",500,_loLimit,_hiLimit);
      _hQuadRawRms[3]=new TH1F("hRawRms3","Quad3, Raw RMS summary",100,0.0,100.0);

      _hQuadSummaryNorm[0]=new TH1F("hSummaryNorm0","Quad0, Norm summary",100,0.0,100000.0);
      _hQuadSummaryMean[0]=new TH1F("hSummaryMean0","Quad0, Mean summary",400,-200.0,200.0);
      _hQuadSummaryRms[0]=new TH1F("hSummaryRms0","Quad0, RMS summary",100,0.0,100.0);
      _hQuadSummaryNorm[1]=new TH1F("hSummaryNorm1","Quad1, Norm summary",100,0.0,100000.0);
      _hQuadSummaryMean[1]=new TH1F("hSummaryMean1","Quad1, Mean summary",400,-200.0,200.0);
      _hQuadSummaryRms[1]=new TH1F("hSummaryRms1","Quad1, RMS summary",100,0.0,100.0);
      _hQuadSummaryNorm[2]=new TH1F("hSummaryNorm2","Quad2, Norm summary",100,0.0,100000.0);
      _hQuadSummaryMean[2]=new TH1F("hSummaryMean2","Quad2, Mean summary",400,-200.0,200.0);
      _hQuadSummaryRms[2]=new TH1F("hSummaryRms2","Quad2, RMS summary",100,0.0,100.0);
      _hQuadSummaryNorm[3]=new TH1F("hSummaryNorm3","Quad3, Norm summary",100,0.0,100000.0);
      _hQuadSummaryMean[3]=new TH1F("hSummaryMean3","Quad3, Mean summary",400,-200.0,200.0);
      _hQuadSummaryRms[3]=new TH1F("hSummaryRms3","Quad3, RMS summary",100,0.0,100.0);
      
      std::ofstream fout("MpsAnalysisLaserTimeScan.txt");

      for(unsigned x(0);x<168;x++) {
	std::cout << "Fitting x = " << x << std::endl;

        for(unsigned y(0);y<168;y++) {
	  if(_hHits[x][y]!=0) {
	    if(_hHits[x][y]->GetEntries()==0) {
	      delete _hHits[x][y];
	      delete _hHitd[x][y];
	    } else {
	      
	      
	      
	      //_pMono[x][y]->Approximate(kTRUE);
	      //_pMono[x][y]->Fit("line");
	      
	      if(_hHits[x][y]->GetMean()==0.0 || 
		 _hHits[x][y]->GetMean()>400.0) {
		std::cout << "Pixel " << x << " " << y << " has mean "
			  << _hHits[x][y]->GetMean() << " and RMS " 
			  << _hHits[x][y]->GetRMS() << std::endl;
	      }
	      
	      
	      _hRawMean->Fill(_hHits[x][y]->GetMean());
	      _hRawRms->Fill(_hHits[x][y]->GetRMS());
	      fout << std::setw(3) << x << " " << std::setw(3) << y << " "
		   << std::setw(12) << _hHits[x][y]->GetMean() << " "
		   << std::setw(12) << _hHits[x][y]->GetRMS() << std::endl;
	      
	      _hQuadRawMean[(x/84)+2*(y/84)]->Fill(_hHits[x][y]->GetMean());
	      _hQuadRawRms[(x/84)+2*(y/84)]->Fill(_hHits[x][y]->GetRMS());
	      
	      
	      _hHits[x][y]->Fit("gaus","Q");
	      double *p(line.GetParameters());
	      //double *e(line.GetParErrors());
	      if(line.GetChisquare()>0.0) {
		//_hMonoSummary->SetBinContent(168*x+y+1,p[1]);
		//_hMonoSummary->SetBinError(168*x+y+1,e[1]);
		_hSummaryNorm->Fill(p[0]);
		_hSummaryMean->Fill(p[1]);
		_hSummaryRms->Fill(p[2]);
		
		_hPixelSummaryNorm->Fill(168*x+y,p[0]);
		_hPixelSummaryMean->Fill(168*x+y,p[1]);
		_hPixelSummaryRms->Fill(168*x+y,p[2]);
		
		_hQuadSummaryNorm[(x/84)+2*(y/84)]->Fill(p[0]);
		_hQuadSummaryMean[(x/84)+2*(y/84)]->Fill(p[1]);
		_hQuadSummaryRms[(x/84)+2*(y/84)]->Fill(p[2]);
	      }
	    }
	  }
	}
      }
      fout.close();
    }
  */


    /*
    for(unsigned s(0);s<_vLocation.size();s++) {
      for(unsigned i(0);i<4;i++) {
	_regionWords[s][i]->runEnd();
	_regionLogWs[s][i]->runEnd();
      }
      
      MpsSensor1ConfigurationData d;
      d.maskSensor(false);
      d.trimSensor(0);
      d.stripCheckBitCounter();
      
      for(unsigned x(0);x<168;x++) {
	if(_hiNorm[s][x/42]>0) {
	  double norm(1.0/_hiNorm[s][x/42]);
	  
	  for(unsigned y(0);y<168;y++) {
	    double fraction(_hiCount[s][x][y]*norm);
	    
	    if(_hiCount[s][x][y]>1 && fraction>0.000001) {
	      std::cout << _sensorTitle[s] << ", x " << std::setw(3) << x
			<< ", y " << std::setw(3) << y
			<< " Hi count = " << std::setw(6)
			<< _hiCount[s][x][y]
			<< ", norm = " << std::setw(10)
			<< _hiNorm[s][x/42]
			<< ", fraction = " << std::setw(10)
			<< fraction << std::endl;

	      d.mask(x,y,true);
	    }
	  }
	}
      }
      
      d.writeFile(_runLabel+_sensorLabel[s]+".cfg");
    }
    */
    endRoot();
  }

  bool runEnd(const RcdRecord &r) {
    endRun();
    /*
    for(unsigned s(0);s<_vLocation.size();s++) {
      for(unsigned i(0);i<4;i++) {
	_regionWords[s][i]->runEnd();
	_regionLogWs[s][i]->runEnd();
      }

      MpsSensor1ConfigurationData d;
      d.maskSensor(false);
      d.trimSensor(0);
      d.stripCheckBitCounter();

      for(unsigned x(0);x<168;x++) {
	if(_hiNorm[s][x/42]>0) {
	  double norm(1.0/_hiNorm[s][x/42]);
	  
	  for(unsigned y(0);y<168;y++) {
	    double fraction(_hiCount[s][x][y]*norm);

	    if(_hiCount[s][x][y]>1 && fraction>0.000001) {
	      std::cout << _sensorTitle[s] << ", x " << std::setw(3) << x
			<< ", y " << std::setw(3) << y
			<< " Hi count = " << std::setw(6)
			<< _hiCount[s][x][y]
			<< ", norm = " << std::setw(10)
			<< _hiNorm[s][x/42]
			<< ", fraction = " << std::setw(10)
			<< fraction << std::endl;

	      d.mask(x,y,true);
	    }
	  }
	}
      }

      d.writeFile(_runLabel+_sensorLabel[s]+".cfg");
    }
    */
    return true;
  }

  bool configurationStart(const RcdRecord &r) {
    for(unsigned s(0);s<_vLocation.size();s++) {
      for(unsigned i(0);i<4;i++) {
	/*
	  _regionWords[s][i]->configurationStart(_vPcbConfigurationData[s].regionThresholdValue(i));
	  _regionLogWs[s][i]->configurationStart(_vPcbConfigurationData[s].regionThresholdValue(i));
	  
	  if(i<2) _hiThreshold[s][i]=_vPcbConfigurationData[s].regionThresholdValue(i)>= 500;
	  else    _hiThreshold[s][i]=_vPcbConfigurationData[s].regionThresholdValue(i)>=1000;
	  }
	  
	  _nBunchTrains[s]=_vUsbDaqConfigurationData[s].spillCycleCount()+1;
	  
	*/
	
	//_thr[i]=_vUsbDaqConfigurationData[s].testTriggerStart();
	_thr[i]=_vUsbDaqConfigurationData[s].spillCycleStart();
	//std::cout << "Sensor " << s << ", region " << i << ", threshold value = " << _thr[i] << std::endl;
      }
    }

    return true;
  }
  
  bool bunchTrain(const RcdRecord &r) {
    SubAccessor accessor(r);

    std::vector<const MpsLocationData<MpsSensor1BunchTrainData>* >
      //w(accessor.access< MpsLocationData<MpsSensor1BunchTrainData> >());
      w(sensor1BunchTrainData(r));
    assert(w.size()==_vLocation.size());

    for(unsigned s(0);s<w.size();s++) {
      if(w[s]!=0) {
	if(doPrint(r.recordType(),1)) w[s]->print(std::cout) << std::endl;

	/*	
	for(unsigned i(0);i<4;i++) {
	  unsigned nWords(w[s]->data()->numberOfRegionHits(i));

	  // For samplers, only count number of hits for small timestamps
	  if(i>=2) {
	    nWords=0;
	    const MpsSensor1BunchTrainDatum *p(w[s]->data()->regionData(i));
	    for(unsigned j(0);j<w[s]->data()->numberOfRegionHits(i);j++) {
	      if(p[j].timeStamp()<500) nWords++;
	    }
	  }

	  _regionWords[s][i]->Fill(nWords);
	  if(nWords>0) {
	    _regionLogWs[s][i]->Fill(std::log10((double)nWords));
	  }
	}
	*/

	for(unsigned region(0);region<4;region++) {
	  const MpsSensor1BunchTrainDatum *p(w[s]->data()->regionData(region));
	  for(unsigned j(0);j<w[s]->data()->numberOfRegionHits(region);j++) {
	    if(p[j].row()<168 && p[j].group()<7) {
	      for(unsigned c(0);c<6;c++) {
		if(p[j].channel(c)) {
		  if(_hHits[c+6*p[j].group()+42*region][p[j].row()]==0) bookHist(c+6*p[j].group()+42*region,p[j].row());
		  _hHits[c+6*p[j].group()+42*region][p[j].row()]->Fill(_thr[region],p[j].timeStamp());
		  _hHit1[c+6*p[j].group()+42*region][p[j].row()]->Fill(_thr[region]);
		}
	      }
	    }
	  }
	}
      }
    }

    return true;
  }


private:
  double _thr[4];

  int _nBins;
  double _loLimit;
  double _hiLimit;
  double _bin;

  double _trim[168][168];

  TH2F *_hHits2;
  TH1F *_hScan;
  TH2F *_hHits[168][168];
  TH1F *_hHit1[168][168];

  TH1F *_hRawMean;
  TH1F *_hRawRms;

  TH1F *_hQuadRawMean[4];
  TH1F *_hQuadRawRms[4];

  TH1F *_hSummaryNorm;
  TH1F *_hSummaryMean;
  TH1F *_hSummaryRms;

  TH1F *_hQuadSummaryNorm[4];
  TH1F *_hQuadSummaryMean[4];
  TH1F *_hQuadSummaryRms[4];

  TH1F *_hPixelSummaryNorm;
  TH1F *_hPixelSummaryMean;
  TH1F *_hPixelSummaryRms;
};

#endif
