#ifndef HstPartCrcScan_HH
#define HstPartCrcScan_HH 1

#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 "TFile.h"

#include "HstBase.hh"
#include "HstTGraphErrors.hh"

#include "UtlAverage.hh"
#include "RcdRecord.hh"
#include "CrcLocationData.hh"
#include "CrcVlinkEventData.hh"
#include "DaqEvent.hh"
#include "SubAccessor.hh"


class HstPartCrcScan : public HstBase {

public:
  HstPartCrcScan(bool i=true) : HstBase(i) {
    for(unsigned i(0);i<22;i++) _slot[i]=false;
    _SLOT = 0;
    _FE = 0;
    _chip = 0;
  }

  HstPartCrcScan(bool i,unsigned FE, unsigned chip) : HstBase(i) {
    for(unsigned i(0);i<22;i++) _slot[i]=false;
    _SLOT = 0;
    _FE = FE;
    _chip = chip;
  }

  HstPartCrcScan(bool i,unsigned SLOT,unsigned FE, unsigned chip) : HstBase(i) {
    for(unsigned i(0);i<22;i++) _slot[i]=false;
    _SLOT= SLOT;
    _FE = FE;
    _chip = chip;
  }


  virtual ~HstPartCrcScan() {
  }


  void autoSetLimits(TH1* hist)
  {
    unsigned entries = (unsigned)hist->GetEntries();
    entries -= (unsigned)hist->GetBinContent(0);
    entries -= (unsigned)hist->GetBinContent(hist->GetNbinsX()+1);
    unsigned counter = 0;
    int bin = 1;
    while (counter/(double)entries < 0.01) counter += (unsigned)hist->GetBinContent(bin++);
    int minBin = bin-1;
    while (counter/(double)entries < 0.99) counter += (unsigned)hist->GetBinContent(bin++);
    hist->GetXaxis()->SetRange(minBin,bin);
  }

  void slotCanvas(unsigned slot) {
    if (slot==_SLOT || _SLOT==0)
      {
	std::cout << "slotCanvas called with slot " << slot << " Label = " << _label[slot] << std::endl;

	_slot[slot]=true;

	_canvas[slot]=new TCanvas(_label[slot].c_str(),_label[slot].c_str(),40,40,1000,600);
	_canvas[slot]->Divide(5,4);


	_graph[slot][0].SetTitle((_label[slot]+", Pedestal vs FE/Chip/Chan").c_str());
	_graph[slot][1].SetTitle((_label[slot]+", Noise vs FE/Chip/Chan").c_str());


	/*	
	for(unsigned fe(0);fe<_maxFrontend;fe++) 
	  if (_feEnabled[fe]) 
	    {
	      for(unsigned chip(0);chip<12;chip++) {
	*/
	
	for(unsigned chan(0);chan<18;chan++) {
	  std::ostringstream sout;
	  sout << _label[slot] << ", FE" << _FE << ", Chip " << std::setw(2) << _chip << ", Chan " << std::setw(2) << chan;
		  
	  _hist[slot][_FE][_chip][chan] = new TH1D(sout.str().c_str(),sout.str().c_str(),(Int_t)(33768/8),-1000,34767);

	}
	 
      }
    else std::cout << "called with slot " << slot << " but only accepting slot 12" << std::endl;
  }


  bool postscript(std::string) {
    TFile *rootout = new TFile("partchannels.root","RECREATE");
    for(unsigned i(0);i<22;i++) {
      if(_slot[i]) {
	for(unsigned chan(0);chan<18;chan++) 
	  {
	    _hist[i][_FE][_chip][chan]->Write();
	  }
      }
    }
    rootout->Write();
    rootout->Close();

    return false;
  }

  bool update() { //bool ps=false) {
    std::cout << "Updating..." << std::endl;

    for(unsigned slot(5);slot<22;slot++) {
      if(_slot[slot]) {
	_graph[slot][0].Set(0);
	_graph[slot][1].Set(0);

	for(unsigned chan(0);chan<18;chan++) {
	  unsigned bin(18*(12*_FE+_chip)+chan);
	  _graph[slot][0].AddPoint(bin,_average[slot][_FE][_chip][chan].average(),0.0,_average[slot][_FE][_chip][chan].errorOnAverage());
	  _graph[slot][1].AddPoint(bin,_average[slot][_FE][_chip][chan].sigma(),0.0,_average[slot][_FE][_chip][chan].errorOnSigma());

	  _average[slot][_FE][_chip][chan].reset();
	}
	 
	
      }
    }
    
    for(unsigned i(0);i<22;i++) {
      if(_slot[i]) {
	_canvas[i]->Clear("D");
	for(unsigned chan(0);chan<18;chan++) {
	  _canvas[i]->cd(chan+1);
	  autoSetLimits(_hist[i][_FE][_chip][chan]);
	  TH1 *histo=_hist[i][_FE][_chip][chan];
	  histo->GetXaxis()->SetLabelSize(0.04);
	  histo->GetYaxis()->SetLabelSize(0.05);
	  histo->Draw();
	}	
	_canvas[i]->cd(19);
	_graph[i][0].Draw("AP");
	_canvas[i]->cd(20);
	_graph[i][1].Draw("AP");
	_canvas[i]->Update();

	char fileName[50];
	sprintf(fileName,"slot%d_allChannels.ps",i);
	_canvas[i]->Print(fileName);
      }
      
    }
    return true;
  }

  bool record(const RcdRecord &r) {


    if(r.recordType()==RcdHeader::runStart) {
      SubAccessor extracter(r);
      std::vector<const CrcLocationData<CrcVmeRunData>* > v(extracter.extract< CrcLocationData<CrcVmeRunData> >());

      for(unsigned i(0);i<v.size();i++) {
	if(!_slot[v[i]->slotNumber()]) {
	  std::ostringstream sout;
	  unsigned sn((v[i]->data()->epromHeader())&0xff);
	  if(sn<10) sout << "SER00" << sn << ", Slot " << std::setw(2) << (unsigned)v[i]->slotNumber();
	  else      sout << "SER0"  << sn << ", Slot " << std::setw(2) << (unsigned)v[i]->slotNumber();
	  _label[v[i]->slotNumber()]=sout.str();
	  slotCanvas(v[i]->slotNumber());
	}
      }
      return true;
    }

    if(r.recordType()!=RcdHeader::event) return true;
    
    SubAccessor extracter(r);
    std::vector<const CrcLocationData<CrcVlinkEventData>* > v(extracter.extract< CrcLocationData<CrcVlinkEventData> >());


    for(unsigned i(0);i<v.size();i++) {
      if(_slot[v[i]->slotNumber()]) {
	const CrcVlinkFeData *fd(v[i]->data()->feData(_FE));
	if(fd!=0) {
	  for(unsigned chan(0);chan<v[i]->data()->feNumberOfAdcSamples(_FE) && chan<18;chan++) {
	    const CrcVlinkAdcSample *as(fd->adcSample(chan));
	    if(as!=0) {
	      _average[v[i]->slotNumber()][_FE][_chip][chan]+=as->adc(_chip);
	      _hist[v[i]->slotNumber()][_FE][_chip][chan]->Fill(as->adc(_chip));
		
	    }
	  }
	}
      }
    }

    return true;
  }

private:
  TCanvas *_canvas[22];

  HstTGraphErrors _graph[22][2];
  TH1D* _hist[22][8][12][18];
  unsigned _SLOT;
  unsigned _FE;
  unsigned _chip;

  bool _slot[22];
  std::string _label[22];
  UtlAverage _average[22][8][12][18];
};

#endif
