#include <signal.h>
#include <iostream>

#include "RcdArena.hh"
#include "RcdRecord.hh"
#include "RcdHeader.hh"
#include "RcdReaderBin.hh"
#include "SubAccessor.hh"

#include "UtlArguments.hh"
#include "UtlTime.hh"

#include "TROOT.h"
#include "TTree.h"
#include "TFile.h"
#include "TApplication.h"
#include "TCanvas.h"
#include "TGraphErrors.h"

using namespace std;

bool continueJob=true;

void signalHandler(int signal) {
  std::cout << "Process " << getpid() << " received signal "
	    << signal << std::endl;
  continueJob=false;
}


void plotRMS(TCanvas* c, TGraphErrors* gr[3], double csum[12],double qcsum[12],double acsum[12],double aqcsum[12], int N) {
  //  for (int i(0);i<3;i++) gr[i]->Reset();

  double x[12];
  double cohN[12],cohNErr[12];
  double incN[12],incNErr[12];
  double totN[12],totNErr[12];
  
  bool exCoh = false;
  bool exInc = false;

  for (int chip(0);chip<12;chip++) {
    x[chip] = chip;
    //    totN[chip] = sqrt((qsum[chip]-sum[chip])/(float)N);
    //    totNErr[chip] = totN[chip]/sqrt(2./(float)N);
    
    incN[chip] = sqrt((aqcsum[chip]-acsum[chip])/(float)N)/sqrt(18.);
    incNErr[chip] = incN[chip]/sqrt(2.*(float)N);
    
    cohN[chip] = sqrt((qcsum[chip] - csum[12] - aqcsum[chip] + acsum[chip])/float(N))/18.;
    cohNErr[chip] = 0;
    
    //    gr[0]->SetPoint(chip,x[chip],totN[chip]);
    //    gr[0]->SetPointError(chip,0,totNErr[chip]);
    gr[1]->SetPoint(chip,x[chip],incN[chip]);
    gr[1]->SetPointError(chip,0,incNErr[chip]);
    if (incN[chip] > 35) exInc = true;
    gr[1]->SetMarkerStyle(21);
    gr[1]->SetTitle("incoherent noise");
    gr[1]->GetXaxis()->SetTitle("chip");
    gr[1]->GetYaxis()->SetTitle("noise (adc)");
    gr[2]->SetPoint(chip,x[chip],cohN[chip]);
    gr[2]->SetPointError(chip,0,cohNErr[chip]);
    if (cohN[chip] > 20) exCoh = true;
    gr[2]->SetMarkerStyle(21);
    gr[2]->GetXaxis()->SetTitle("chip");
    gr[2]->GetYaxis()->SetTitle("noise (adc)");
    gr[2]->SetTitle("coherent noise");

  }

  if (exInc) gr[1]->GetYaxis()->UnZoom();
  else gr[1]->GetYaxis()->SetRangeUser(0,35);
  if (exCoh) gr[2]->GetYaxis()->UnZoom();
  else  gr[2]->GetYaxis()->SetRangeUser(0,20);

  for (int i(1);i<3;i++) {
    c->cd(i);

    gr[i]->Draw("AP");
  }

}

int main(int argc, const char **argv) {
  UtlArguments argh(argc,argv);

  const unsigned slot(argh.optionArgument('s',0,"Slot"));
  const unsigned Nevent(argh.optionArgument('N',900,"No. of events between updates of screen"));
  const unsigned selectedFE(argh.optionArgument('F',8,"frontend - needed for some histograms"));
  //  const unsigned selectedChip(argh.optionArgument('C',8,"chip - needed for some histograms"));
  const unsigned vnum(argh.lastArgument(999999));


  argh.print(cout,"*");

  ostringstream sout;
  sout << vnum;

  RcdReaderBin reader;
  RcdArena arena;


  reader.open(string("data/run/Run")+sout.str()+string(".000"));

  unsigned counter(0);

  double sum[22][8][12][18],qsum[22][8][12][18],csum[22][8][12],qcsum[22][8][12],acsum[22][8][12],qacsum[22][8][12];

  int nRMS=0;

  for (int s(0);s<22;s++)
    for (int f(0);f<8;f++)
      for (int i(0);i<12;i++) {
	for (int a(0);a<18;a++) {
	  sum[s][f][i][a] =0;
	  qsum[s][f][i][s] =0;
	}
	csum[s][f][i] = 0;
	acsum[s][f][i] = 0;
	qcsum[s][f][i] = 0;
	qacsum[s][f][i] = 0;
      }

  TApplication myApp("RMS",0,0);
  TCanvas *c = new TCanvas("Noise","Noise",500,800);
  c->Divide(1,2);
  TGraphErrors *gr[3];

  for (int i=0;i<3;i++) gr[i] = new TGraphErrors(12);

  while (reader.read(arena)) {

    if (arena.recordType()==RcdHeader::event){

      counter++;

      SubAccessor extracter(arena);
      std::vector<const CrcLocationData<CrcVlinkEventData>* > v(extracter.extract< CrcLocationData<CrcVlinkEventData> >());

      UtlTime actualTime(true);
      if ((actualTime - arena.recordTime()).seconds() < 2) 	{
	cout << "waiting for new data ..." << "\r" <<flush;
	sleep(2);
      }

      //      event.time[0]= arena.recordTime().seconds();
      //      event.time[1]= arena.recordTime().microseconds();
      for(unsigned i(0);i<v.size();i++) {
	if(v[i]->slotNumber()==slot || slot==0 ) {
	  for(unsigned fe(0);fe<8;fe++) {
	    const CrcVlinkFeData *fd(v[i]->data()->feData(fe));
	    if(fd!=0) {
	      double adc[12][18];
	      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++) {
		    adc[chip][chan] = as->adc(chip);
		    sum[v[i]->slotNumber()][fe][chip][chan] += adc[chip][chan];
		    qsum[v[i]->slotNumber()][fe][chip][chan] += pow(adc[chip][chan],2.);
		  }
		}
	      }
	      if (counter >1000)
		for(unsigned chip(0);chip<12;chip++) {
		  double directSum =0;
		  double alterSum =0;
		  for(unsigned chan(0);chan<v[i]->data()->feNumberOfAdcSamples(fe) && chan<18;chan++)  {
		    double mean = sum[v[i]->slotNumber()][fe][chip][chan]/(float)counter;
		    directSum += adc[chip][chan]-mean;
		    alterSum += pow(-1.,1.*chan)*(adc[chip][chan]-mean);
		  }
		  csum[v[i]->slotNumber()][fe][chip] +=   directSum;
		  qcsum[v[i]->slotNumber()][fe][chip] +=   pow(directSum,2.);
		  acsum[v[i]->slotNumber()][fe][chip] +=   alterSum; 
		  qacsum[v[i]->slotNumber()][fe][chip] +=   pow(alterSum,2.);  
		  nRMS++;
		}
	    }
	  }
	}
      }
    

      if (counter%Nevent==0) {
	//	hn->update();
	cout << counter << " " <<nRMS << endl;
	plotRMS(c,gr,csum[slot][selectedFE],qcsum[slot][selectedFE],acsum[slot][selectedFE],qacsum[slot][selectedFE],nRMS/12);
	c->Update();
	//	hn->postscript("bla");
      }

    }


      
  }
  plotRMS(c,gr,csum[slot][selectedFE],qcsum[slot][selectedFE],acsum[slot][selectedFE],qacsum[slot][selectedFE],nRMS/12);
  c->Update();

  char psName[512];
  sprintf(psName,"noise_run%d.ps",vnum);
  c->Print(psName);
    


}
