#ifndef HstHoldScan_HH
#define HstHoldScan_HH

#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 "TFitter.h"
#include "TStyle.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 HstHoldScan : public HstBase {

public:
  HstHoldScan(bool i=true) : HstBase(i) {
    for(unsigned i(0);i<22;i++) _slot[i]=false;
    _SLOT = 12;
    _FRONTEND = 0;
    _CHIP = 0;
    _CHANNEL = 0;
  }

  HstHoldScan(bool i=true,unsigned selectedFrontend=0) : HstBase(i) {
    for(unsigned i(0);i<22;i++) _slot[i]=false;
    _SLOT = 12;
    _FRONTEND=selectedFrontend;
    _CHIP = 0;
    _CHANNEL = 0;
  } 


  virtual ~HstHoldScan() {
  }

  void channelCanvas(unsigned slot, unsigned fe, unsigned chip, unsigned chan) {
    std::cout << "channelCanvas called with slot " << slot << " fe = " << fe << " chip = " << chip << " chan = "<< chan << " Label = " << _label[slot] << std::endl;

    _slot[slot]=true;
    
    _canvas[slot]=new TCanvas(_label[slot].c_str(),_label[slot].c_str(),400+10*slot,10+10*slot,400,600);
    _canvas[slot]->Divide(1,1);

    gStyle->SetOptFit(111);
    gStyle->SetFitFormat("12.6g");
    
    //_graph[slot][0].Set(96);
    _graph[slot][0].SetTitle((_label[slot]+", single channel spectrum").c_str());
    //_graph[slot][0].SetMarkerColor(1);
    //_graph[slot][0].SetMarkerStyle(20);
      

    ostringstream sout;
    sout << _label[slot] << ", FE" << fe << ", Chip " << std::setw(2) << chip << ", Chan " << std::setw(2) << chan;
 
    //_hist[slot][fe][chip][chan].Reset();
    _hist[slot][fe][chip][chan].SetNameTitle(sout.str().c_str(),sout.str().c_str());
    _hist[slot][fe][chip][chan].SetBins(65536,-32768,32768);


    fitgaus[chan]=new TF1("fitgaus","gaus",500,1500);

  }

  bool postscript(std::string) {
    for(unsigned i(0);i<22;i++) {
      if(_slot[i]) {
	ostringstream sout;
	sout << "dps/HoldScanSER0" << _label[i][4] << _label[i][5] << ".ps";
	_canvas[i]->Print(sout.str().c_str());
      }
    }
    return false;
  }


  bool update() { //bool ps=false) {
    std::cout << "Updating..." << std::endl;
    unsigned slot = _SLOT ;
    unsigned fe = _FRONTEND ;
    unsigned chip = _CHIP ;
    unsigned chan = _CHANNEL ;


    
      if(_slot[slot]) {

	//	_hist[slot][fe][chip][chan].SetBins(200,unsigned(_average[slot][fe][chip][chan].average())-50,unsigned(_average[slot][fe][chip][chan].average())+150);
       	_hist[slot][fe][chip][chan].SetBins(30000,0,30000);
	cout << "HIER2: " << _average[slot][fe][chip][chan].average() << endl ;
	      
	// _average[slot][fe][chip][chan].reset();

	//	_canvas[slot]->Clear("D");

	_canvas[slot]->cd(1);

	_hist[slot][fe][chip][chan].SetMarkerColor(1);
	_hist[slot][fe][chip][chan].SetLineColor(4);
	_hist[slot][fe][chip][chan].SetLineWidth(2);
	_hist[slot][fe][chip][chan].SetMarkerStyle(20);
	_hist[slot][fe][chip][chan].SetNdivisions(505);
	_hist[slot][fe][chip][chan].Draw("AP");
	//	_hist[slot][fe][chip][chan].Fit("gaus");
        
	fitgaus[chan]->SetRange(unsigned(_average[slot][fe][chip][chan].average())-500,unsigned(_average[slot][fe][chip][chan].average())+500);
        _hist[slot][fe][chip][chan].Fit(fitgaus[chan],"R");

	_canvas[slot]->Update();
      }
    
    return true;
  }

  bool record(const RcdRecord &r) {

    unsigned fe = _FRONTEND ;
    unsigned chip = _CHIP ;
    unsigned chan = _CHANNEL ;

    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();
	  channelCanvas(v[i]->slotNumber(), fe, chip, chan);
	}
      }
      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()]) {
        for(unsigned fe(0);fe<8;fe++) {
          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) {
                for(unsigned chip(0);chip<12;chip++) {
	
		  if ((fe == _FRONTEND) && (chip==_CHIP))  
		    {
		      _average[v[i]->slotNumber()][fe][chip][chan]+=as->adc(chip);
		      _hist[v[i]->slotNumber()][fe][chip][chan].Fill(as->adc(chip));
		    }
	
		}
	      }
	    }
	  }
	}
      }
    }


  	
      
    return true;
  }


  double getmean(unsigned slot, unsigned fe, unsigned chip, unsigned chan, double* fitMean, double* RMS) {

    double temp = _average[slot][fe][chip][chan].average();
    //    _hist[slot][fe][chip][chan].Fit(fitgaus[chan],"R");
    *fitMean = fitgaus[chan]->GetParameter(1);
    *RMS = fitgaus[chan]->GetParameter(2);   

    cout << "HERE: " <<  _average[slot][fe][chip][chan].average() << endl ;
    cout <<  _hist[slot][fe][chip][chan].GetEntries() << endl ;

    _average[slot][fe][chip][chan].reset();
    _hist[slot][fe][chip][chan].Reset();

    return temp;

  }

private:
 
  unsigned _SLOT;
  unsigned _FRONTEND;
  unsigned _CHIP;
  unsigned _CHANNEL;
  

  TCanvas *_canvas[22];

  //TGraphErrors _graph[22][2];
  HstTGraphErrors _graph[22][2];
  TH1D _hist[22][8][12][18];
  TF1 *fitgaus[18];

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

#endif
