#ifndef HstChipChannel_HH
#define HstChipChannel_HH

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>

#include "TROOT.h"
#include "TApplication.h"
#include "TCanvas.h"
#include "TF1.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 HstChipChannel : public HstBase {

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

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


  virtual ~HstChipChannel() {
  }

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

    _SLOT = slot;
    _slot[slot]=true;
    
    _canvas[slot][0]=new TCanvas((_label[slot]+"0").c_str(),_label[slot].c_str(),200,50,400,600);
    _canvas[slot][0]->Divide(3,3);
    _canvas[slot][1]=new TCanvas((_label[slot]+"1").c_str(),_label[slot].c_str(),700,50,400,600);
    _canvas[slot][1]->Divide(3,3);

    gStyle->SetOptFit(111);
    gStyle->SetFitFormat("12.6g");
    
    //_graph[slot][0].Set(96);
    /*
    for(unsigned i(0);i<18;i++) {
      char dummy[50];
      sprintf(dummy, (_label[slot]+", channel spectrum").c_str() + "%d", i);
      //_graph[slot][i].SetTitle(dummy);
      //_graph[slot][0].SetMarkerColor(1);
      //_graph[slot][0].SetMarkerStyle(20);
    }
    */
    //    for(unsigned fe(0);fe<8;fe++) {
    //  for(unsigned chip(0);chip<12;chip++) {
	unsigned fe = _FRONTEND;
	unsigned chip = _CHIP;
	for(unsigned chan(0);chan<18;chan++) {
	  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(100,-30000,30000);
	  _hist[slot][fe][chip][chan].SetBins(65536,-32768,32768);
	  // for HAB connected
	  fitgaus[chan]=new TF1("fitgaus","gaus",500,1500);
	  // for HAB disconnected = CRC noise
	  //if ((fe==0) && (chip==0)) fitgaus[chan]=new TF1("fitgaus","gaus",-25,25);
	  //	}
	  // }
    }
  }
  

  bool postscript(std::string) {
    for(unsigned i(0);i<22;i++) {
      if(_slot[i]) {
	ostringstream sout1;
	sout1 << "dps/18ChanSER0" << _label[i][4] << _label[i][5] << "_1.ps";
	_canvas[i][0]->Print(sout1.str().c_str());
	ostringstream sout2;
	sout2 << "dps/18ChanSER0" << _label[i][4] << _label[i][5] << "_2.ps";
	_canvas[i][1]->Print(sout2.str().c_str());

	TFile *histFile = new TFile("oneChip.root","RECREATE");
	
	for (int j(0);j<18;j++) _hist[i][_FRONTEND][_CHIP][j].Write();
    
	histFile->Write();
	histFile->Close();
	

	ofstream asciout;

	asciout.open("oneChip.dat");
    
	for (int j(-32768);j<32768;j++)
	  {
	    asciout << j << "  ";
	    for (int k(0);k<18;k++)
	      {
		if (_hist[i][_FRONTEND][_CHIP][k].GetXaxis()->GetXmin()<=j && _hist[i][_FRONTEND][_CHIP][k].GetXaxis()->GetXmax()>=j) asciout << _hist[i][_FRONTEND][_CHIP][k].GetBinContent(j-(int)_hist[i][_FRONTEND][_CHIP][k].GetXaxis()->GetXmin()) << "  ";
		else asciout << "0  "; 
	  }
	    asciout << endl;
	  }
	asciout.close();

      }
    }

    return false;
  }


  bool update() { //bool ps=false) {
    std::cout << "Updating..." << std::endl;
    unsigned slot = 12 ;
    unsigned fe = 0;
    unsigned chip = _CHIP ;
    // unsigned chan = 0 ;
    fe = _FRONTEND;
    if(_slot[slot]) {
      //_graph[slot][0].Set(0);
      //unsigned bin(18*(12*fe+chip)+chan);
	
      //_graph[slot][0].AddPoit(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();
      
      // output file for fit values
      ofstream file;
      file.open( "noise_fitvalues.txt" );
      file.write("# channel  events  mean_fit  rms_fit  mean_hist  rms_hist   \n",60);
      unsigned entries=0;
      unsigned nfit=0;
      for(unsigned j(0);j<2;j++){
	for(unsigned i(0);i<9;i++){
	  // for HAB connected
	  //_hist[slot][fe][chip][i+(j*9)].SetBins(2000,unsigned(_average[slot][fe][chip][i+(j*9)].average())-500,unsigned(_average[slot][fe][chip][i+(j*9)].average())+1500);
	  _hist[slot][fe][chip][i+(j*9)].SetBins(2000,0,2000);

	  
	  // for HAB disconnected = CRC noise
	  //_hist[slot][fe][chip][i+(j*9)].SetBins(50,signed(_average[slot][fe][chip][i+(j*9)].average())-25,signed(_average[slot][fe][chip][i+(j*9)].average())+25);
	  // if (_hist[slot][fe][chip][i+(j*9)].GetMean() < 850 ) _hist[slot][fe][chip][i+(j*9)].Reset();
      

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

	  _canvas[slot][j]->cd(i+1);
	  
	  _hist[slot][fe][chip][i+(j*9)].SetMarkerColor(1);
	  _hist[slot][fe][chip][i+(j*9)].SetLineColor(4);
	  _hist[slot][fe][chip][i+(j*9)].SetLineWidth(2);
	  _hist[slot][fe][chip][i+(j*9)].SetMarkerStyle(20);
	  _hist[slot][fe][chip][i+(j*9)].SetNdivisions(505);

	  //   _hist[slot][fe][chip][i+(j*9)].Fit("gaus");
         

          entries = (unsigned)_hist[slot][fe][chip][i+(j*9)].GetEntries();
 	  if ( (entries>1000) && ((entries/1000) > nfit)) {
	    if (i+(j*9) == 17) nfit++;

	    _hist[slot][fe][chip][i+(j*9)].Draw("AP");
	    fitgaus[i+(j*9)]->SetRange(unsigned(_average[slot][fe][chip][i+(j*9)].average())-500,unsigned(_average[slot][fe][chip][i+(j*9)].average())+500);
	    _hist[slot][fe][chip][i+(j*9)].Fit(fitgaus[i+(j*9)],"R");
	    double mean = fitgaus[i+(j*9)]->GetParameter(1);
	    double rms = fitgaus[i+(j*9)]->GetParameter(2);
	    double mean_hist = _hist[slot][fe][chip][i+(j*9)].GetMean();
	    double rms_hist = _hist[slot][fe][chip][i+(j*9)].GetRMS();
	    
	    // get fit-values: mean and RMS and dump into a file

	    char dummy[50];
	    sprintf(dummy, "\n%2d  %6d  %3.3f  %f  %3.3f  %f       ",i+1+(j*9),entries,mean,rms,mean_hist,rms_hist);
	  
	 
	    file.write( (char*)&dummy, sizeof(dummy)-1);
	  }
      
	    
	  _average[slot][fe][chip][i+(j*9)].reset();
	}

	if (entries>1000)  _canvas[slot][j]->Update();
	cout << "Entries: " << entries << endl ;
      }
      // close file for fit values
      file.close();
    }
    return true;
 
  }


  bool record(const RcdRecord &r) {

    //    unsigned fe = 2 ;
    //    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());
	}
      }
      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( as->adc(chip) > 0 ) {

		  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;
  }

private:

  unsigned _FRONTEND, _SLOT;
  unsigned static const _CHIP=0 ;
  TCanvas *_canvas[22][2];
  TF1 *fitgaus[18];

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

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

#endif
