
#ifndef HstOneChannel_HH
#define HstOneChannel_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 HstOneChannel : public HstBase {

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

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

  virtual ~HstOneChannel() {
  }

  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].SetNameTitle(sout.str().c_str(),sout.str().c_str());
    _hist[slot][fe][chip][chan].SetBins(65536,-32768,32768);


  }

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


	TFile *histFile = new TFile("oneChannel.root","RECREATE");
	
	_hist[i][_FRONTEND][0][0].Write();

	histFile->Write();
	histFile->Close();
	

	ofstream asciout;

	asciout.open("oneChannel.dat");
    
	for (int j((int)_hist[i][_FRONTEND][0][0].GetXaxis()->GetXmin()+1);j<(int)_hist[i][_FRONTEND][0][0].GetXaxis()->GetXmax();j++)
	  {
	    asciout << j << "  ";

	    asciout << _hist[i][_FRONTEND][0][0].GetBinContent(j-(int)_hist[i][_FRONTEND][0][0].GetXaxis()->GetXmin()) << "  ";
	    
	    asciout << endl;
	  }
	asciout.close();




      }
    }
    return false;
  }


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

    fe = _FRONTEND;


    
      if(_slot[slot]) {
	_graph[slot][0].Set(0);
	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());

	//if (_hist[slot][fe][chip][chan].GetEntries() >= 1000 ) _hist[slot][fe][chip][chan].Reset();

	//	_hist[slot][fe][chip][chan].SetBins(2000,unsigned(_average[slot][fe][chip][chan].average())-500,unsigned(_average[slot][fe][chip][chan].average())+1500);

	// for DNL scan
		_hist[slot][fe][chip][chan].SetBins(33268,-500,32768);
	//_hist[slot][fe][chip][chan].SetBins(500,500,1000);
       
	      
	//_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");

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

  bool record(const RcdRecord &r) {

    unsigned fe = _FRONTEND;
    unsigned chip = 0 ;
    unsigned chan = 0 ;

    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()]) {
          const CrcVlinkFeData *fd(v[i]->data()->feData(fe));
          if(fd!=0) { 
              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;
  }


  double getmean(unsigned slot, unsigned fe, unsigned chip, unsigned chan) {
    
    return _average[slot][fe][chip][chan].average();
    _average[slot][fe][chip][chan].reset();

  }

private:
  unsigned _SLOT;
  unsigned _FRONTEND;
  TCanvas *_canvas[22];

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

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

#endif
