#include <utils/yodaUtility.h>
#include "TrkFunctions.cpp"
#include <iostream>
#include <fstream>
#include <TPaveText.h>
#include <TLatex.h>
#include <TCanvas.h>
#include <TGraph.h>
#include <TStyle.h>
#include <TObjString.h>
#include <PscuHeader.h>
#include <EventHeader.h>
#include <CalibTrk1Event.h>
#include <CalibTrk2Event.h>

/**
 * TrkCalibQLookBasic.cpp
 *
 * autor: D.Fedele
 * version 1.0
 * Parameters:
 * 	base - the path to the root directory for the specific
 *	       Pamela unpack session
 *      fromevent - first event to analyse
 *      toevent - last event to analyse
 *      outdir - total path of output file 
 * 	outfile - extension of output file (pdf,ps,gif,jpg)
 * 
 */

void TrkCalibQLook_BASIC(TString file,Int_t fromevent,Int_t toevent,TString outdir,TString outfile)
{
  // 
  //   obtain information about the data file and select the output dir
  const string filepath=file.Data(); 
  Int_t dwpos = filepath.find("DW_");
  Int_t dwpos1 = filepath.find(".root");
  TString fpath=(filepath.c_str());
  TString base,ffile;
  stringcopy(base,fpath,0,dwpos);
  stringcopy(ffile,fpath,dwpos,dwpos1);

  TString out;
  if(outdir.Length()==0){
    out = base;
  }else{
    out = outdir;
  };
  
  //
  // inizialise the variables and open the file
  struct caltrk_def ctrk;
  Int_t nevents=0;
  Int_t minevent = 0;
  Int_t maxevent = 0;
  ULong64_t OBT[2];
  
  OBT[0]=0;
  OBT[1]=0;
  ctrk.good0[0]=0;
  ctrk.good0[1]=0;
  for(Int_t i=0;i<12;i++){ 
    ctrk.daqmode[i]=0;
    ctrk.dspnum[i]=0;
    ctrk.calibnum[i]=0;
    ctrk.ncalev[i]=0;
    ctrk.calfl[i]=0;
    ctrk.ped1[i]=0;
    ctrk.ped2[i]=0;
    ctrk.ped3[i]=0;
    ctrk.sig1[i]=0;
    ctrk.sig2[i]=0;
    ctrk.sig3[i]=0;
    ctrk.nbad1[i]=0;
    ctrk.nbad2[i]=0;
    ctrk.nbad3[i]=0;
    ctrk.crc_hc[i]=0;
    ctrk.crc_c[i][0]=0;
    ctrk.crc_c[i][1]=0;
    ctrk.crc_c[i][2]=0;
    for(Int_t iii=0;iii<3072;iii++){
      ctrk.dspped[i][iii]=0;
      ctrk.dspsig[i][iii]=0;
      ctrk.dspbad[i][iii]=0;
    }
  }

  pamela::EventHeader *eh1=0,*eh2=0;
  pamela::PscuHeader *ph1=0,*ph2=0;
  pamela::CalibTrk1Event *trk1 = 0;
  pamela::CalibTrk2Event *trk2 = 0;

  TFile *datafile = new TFile(file);
  if ( !datafile ){
    printf("No data file, exiting...\n");
    return;
  };  
  TTree *otr1,*otr2;
  
  otr1 = (TTree*)datafile->Get("CalibTrk1");
  otr1->SetBranchAddress("CalibTrk1", &trk1);
  otr1->SetBranchAddress("Header",&eh1);
  otr2 = (TTree*)datafile->Get("CalibTrk2");
  otr2->SetBranchAddress("CalibTrk2", &trk2);
  otr2->SetBranchAddress("Header",&eh2);
  

  if(otr1->GetEntries()==otr2->GetEntries())
    nevents = otr1->GetEntries();
  else{
    printf("WARNING: CalibTrk1 entries is different from CalibTrk2 entries");
    return;}

  if (nevents<=0) {
    datafile->Close();
    printf("No calibration packets found, exiting...\n");
    return;
  };
  // printf("Number of calibration packets: %i\n",nevents);

  if ( fromevent > toevent && toevent ){
    printf("It must be fromevent < toevent \n");
    return;
  };
    
  if ( fromevent > nevents || fromevent < 0 ) {
    printf("You can choose fromevent between 0 (all) and %i \n",nevents);
    return;
  };
    
  if ( toevent > nevents || toevent < 0 ) {
    printf("You can choose toevent between 0 (all) and %i \n",nevents);
    return;
  };
  if ( fromevent == 0 ) {
    minevent = 0;
    maxevent = nevents;
  } else {
    minevent = fromevent - 1;
    if ( toevent > 0 ){
      maxevent = toevent;
    } else if (toevent > nevents) {	   
      maxevent = nevents;
    } else {	   
      maxevent = fromevent;
    };
  };

  //
  // other variables definitions
  stringstream fromfile,rep,tit;
  fromfile<<"TrkCalibQLookBasic      File: "<<ffile;
  
  gStyle->SetLabelSize(0.08,"x");
  gStyle->SetLabelSize(0.08,"y");
  gStyle->SetFillColor(0); 
  gStyle->SetTitleFillColor(0); 
  gStyle->SetTitleFontSize(0.1);
  gStyle->SetTitleOffset(0.8,"y");
  gStyle->SetTitleOffset(1.,"x");
  gStyle->SetTitleSize(0.06,"y");
  gStyle->SetTitleSize(0.06,"x");
  gStyle->SetOptStat(0);

  TLatex *tzz=new TLatex();
  tzz->SetTextFont(32);
  tzz->SetTextColor(1);
  tzz->SetTextAlign(12);
  tzz->SetTextSize(0.02);

  Int_t canvasx=900;
  Int_t canvasy=1200;

  Int_t ndsp =0,alarm=0;
  Float_t pedav[12][12],pedavtemp[12][12],sigav[12][12],sigavtemp[12][12];
  Int_t flpedav[12][12],flsigav[12][12];
  Float_t siglimsup[12][12],sigliminf[12][12],pedlimsup[12][12],pedliminf[12][12];

  //
  // inizialize the limits for simga and pedestall
  for(Int_t i=0;i<12;i++){
    for(Int_t ii=0;ii<12;ii++){
      siglimsup[i][ii]=20.;
      sigliminf[i][ii]=0.;
      pedlimsup[i][ii]=3500.;
      pedliminf[i][ii]=50.;
    }
  }
  
  //
  // count of possible alarm to set the number of output pages
  alarm+=(maxevent-minevent)/9 +1;
  for (Int_t i = minevent; i < maxevent; i++){     
    otr1->GetEntry(i); 
    otr2->GetEntry(i); 
    for(Int_t m=0;m<6;m++){
      for(Int_t mm=0;mm<3;mm++){
	if(trk1->crc_cal[m][mm]!=0) alarm+=1;
	if(trk2->crc_cal[m][mm]!=0 ) alarm+=1;
      }
      if(trk1->crc_hcal[m]!=0 ) alarm+=1;
      if(trk1->cal_flag[m]!=0 ) alarm+=1;
      if(trk2->crc_hcal[m]!=0) alarm+=1;
      if(trk2->cal_flag[m]!=0) alarm+=1;
    }  
  }
  const Int_t cnum=alarm/30 + 10;
  Int_t flcanvas=1;
  Float_t spacep=1.5,space[cnum];
  TCanvas *c[cnum];
  
  //
  //  create output canvas  
  for(Int_t i=0;i<cnum;i++){
    space[i]=96.0;
    rep.str("");
    tit.str("");
    tit<<"c"<<i;
    rep<<"TrkCalibQLook_BASIC_pag"<<i+1;
    c[i]=new TCanvas(tit.str().c_str(),rep.str().c_str(),canvasx,canvasy);
    c[i]->Range(0,0,100,100);
    tzz->DrawLatex(1,98.5,fromfile.str().c_str());
    rep.str("");
    rep<<"CALIBRATION REPORT pag"<<i+1;
    tzz->DrawLatex(70,98.5,rep.str().c_str());
    rep.str("");
  }


  //**********************************************************************
  //
  //   LOOP OVER EVENTS
  //
  //**********************************************************************
  
  Int_t wc=0;
  //   printf("\n Scan of calibration packets from %i to %i ... \n",minevent+1,maxevent);
  for (Int_t i = minevent; i < maxevent; i++){     
      
    otr1->GetEntry(i); 
    otr2->GetEntry(i); 
      
    ctrk.good0[0]=trk1->good0;
    ctrk.good0[1]=trk2->good0;
    for (Int_t m = 0; m < 6; m++){
      ph1 = eh1->GetPscuHeader();
      OBT[0]= ph1->GetOrbitalTime();
      ctrk.daqmode[trk1->DSPnumber[m]-1]=trk1->DAQmode[m];
      ctrk.dspnum[trk1->DSPnumber[m]-1]=trk1->DSPnumber[m];
      ctrk.calibnum[trk1->DSPnumber[m]-1]=trk1->calibnumber[m];
      ctrk.ncalev[trk1->DSPnumber[m]-1]=trk1->ncalib_event[m];
      ctrk.ped1[trk1->DSPnumber[m]-1]=trk1->ped_l1[m];
      ctrk.ped2[trk1->DSPnumber[m]-1]=trk1->ped_l2[m];
      ctrk.ped3[trk1->DSPnumber[m]-1]=trk1->ped_l3[m];
      ctrk.sig1[trk1->DSPnumber[m]-1]=trk1->sig_l1[m];
      ctrk.sig2[trk1->DSPnumber[m]-1]=trk1->sig_l2[m];
      ctrk.sig3[trk1->DSPnumber[m]-1]=trk1->sig_l3[m];
      ctrk.nbad1[trk1->DSPnumber[m]-1]=trk1->nbad_l1[m];
      ctrk.nbad2[trk1->DSPnumber[m]-1]=trk1->nbad_l2[m];
      ctrk.nbad3[trk1->DSPnumber[m]-1]=trk1->nbad_l3[m];
      ctrk.calfl[trk1->DSPnumber[m]-1]=trk1->cal_flag[m];
      ctrk.crc_c[trk1->DSPnumber[m]-1][0]=trk1->crc_cal[m][0];
      ctrk.crc_c[trk1->DSPnumber[m]-1][1]=trk1->crc_cal[m][1];
      ctrk.crc_c[trk1->DSPnumber[m]-1][2]=trk1->crc_cal[m][2];
      ctrk.crc_hc[trk1->DSPnumber[m]-1]=trk1->crc_hcal[m];
      for (Int_t j = 0; j < 3072; j++){
	ctrk.dspped[trk1->DSPnumber[m]-1][j]=trk1->DSPped_par[m][j];
	ctrk.dspsig[trk1->DSPnumber[m]-1][j]=trk1->DSPsig_par[m][j];
	ctrk.dspbad[trk1->DSPnumber[m]-1][j]=trk1->DSPbad_par[m][j];
      }
      ph2 = eh2->GetPscuHeader();
      OBT[1]= ph2->GetOrbitalTime();
      ctrk.daqmode[trk2->DSPnumber[m]-1]=trk2->DAQmode[m];
      ctrk.dspnum[trk2->DSPnumber[m]-1]=trk2->DSPnumber[m];
      ctrk.calibnum[trk2->DSPnumber[m]-1]=trk2->calibnumber[m];
      ctrk.ncalev[trk2->DSPnumber[m]-1]=trk2->ncalib_event[m];
      ctrk.ped1[trk2->DSPnumber[m]-1]=trk2->ped_l1[m];
      ctrk.ped2[trk2->DSPnumber[m]-1]=trk2->ped_l2[m];
      ctrk.ped3[trk2->DSPnumber[m]-1]=trk2->ped_l3[m];
      ctrk.sig1[trk2->DSPnumber[m]-1]=trk2->sig_l1[m];
      ctrk.sig2[trk2->DSPnumber[m]-1]=trk2->sig_l2[m];
      ctrk.sig3[trk2->DSPnumber[m]-1]=trk2->sig_l3[m];
      ctrk.nbad1[trk2->DSPnumber[m]-1]=trk2->nbad_l1[m];
      ctrk.nbad2[trk2->DSPnumber[m]-1]=trk2->nbad_l2[m];
      ctrk.nbad3[trk2->DSPnumber[m]-1]=trk2->nbad_l3[m];
      ctrk.calfl[trk2->DSPnumber[m]-1]=trk2->cal_flag[m];
      ctrk.crc_c[trk1->DSPnumber[m]-1][0]=trk2->crc_cal[m][0];
      ctrk.crc_c[trk1->DSPnumber[m]-1][1]=trk2->crc_cal[m][1];
      ctrk.crc_c[trk1->DSPnumber[m]-1][2]=trk2->crc_cal[m][2];
      ctrk.crc_hc[trk1->DSPnumber[m]-1]=trk2->crc_hcal[m];
      for (Int_t j = 0; j < 3072; j++){
	ctrk.dspped[trk2->DSPnumber[m]-1][j]=trk2->DSPped_par[m][j];
	ctrk.dspsig[trk2->DSPnumber[m]-1][j]=trk2->DSPsig_par[m][j];
	ctrk.dspbad[trk2->DSPnumber[m]-1][j]=trk2->DSPbad_par[m][j];
      }
    }  

    for(Int_t n = 0; n<12; n++){
      for(Int_t nm = 0; nm<12; nm++){
	pedav[n][nm]=0;
	pedavtemp[n][nm]=0;
	sigav[n][nm]=0;
	sigavtemp[n][nm]=0;
	flpedav[n][nm]=0;
	flsigav[n][nm]=0;
      }
    }
    
    Int_t nn,ok=0;
    
    //
    // write warning if it occur      
    for(Int_t n = 0; n<12; n++){
      
      ndsp = ctrk.dspnum[n];
      nn = ndsp-1;

      for(Int_t iii=0;iii<3;iii++){
	if(ctrk.crc_c[nn][iii]!=0){
	  ok=1;
	  if(space[wc]<=3){
	    wc+=1;
	    flcanvas+=1;
	  }
	  c[wc]->cd();
	  tzz->SetTextFont(40);
	  tzz->SetTextSize(0.02);
	  tzz->SetTextAlign(13);
	  tzz->SetTextColor(2);
	  rep<<"***************************************************************************************************************************";
	  tzz->DrawLatex(2,space[wc],rep.str().c_str());
	  rep.str("");
	  space[wc]-=spacep;
	  rep<<" ERROR >>> CALIBRATION pkt "<<i+1<<" -->CalibTrk"<<(nn+1)%2+1<<" at OBT: "<<OBT[(nn+1)%2]<<" --> crc_cal["<<nn+1<<"]["<<iii+1<<"]= "<<ctrk.crc_c[nn][iii];
	  tzz->DrawLatex(2,space[wc],rep.str().c_str());
	  rep.str("");
	  space[wc]-=spacep;
	}
      }
	  
      if(ctrk.crc_hc[nn]!=0){
	ok=1;
	if(space[wc]<=3){
	  wc+=1;
	  flcanvas+=1;
	}
	c[wc]->cd();
	tzz->SetTextFont(40);
	tzz->SetTextSize(0.02);
	tzz->SetTextAlign(13);
	tzz->SetTextColor(2);
	rep<<"***************************************************************************************************************************";
	tzz->DrawLatex(2,space[wc],rep.str().c_str());
	rep.str("");
	space[wc]-=spacep;
	rep<<" ERROR >>> CALIBRATION pkt "<<i+1<<" -->CalibTrk"<<(nn+1)%2+1<<" at OBT: "<<OBT[(nn+1)%2]<<" --> crc_hcal["<<nn+1<<"]= "<<ctrk.crc_hc[nn];
	tzz->DrawLatex(2,space[wc],rep.str().c_str());
	rep.str("");
	space[wc]-=spacep;
      }
      
      if(ctrk.calfl[nn]!=0){
	ok=1;
	if(space[wc]<=3){
	  wc+=1;
	  flcanvas+=1;
	}
	c[wc]->cd();
	tzz->SetTextFont(40);
	tzz->SetTextSize(0.02);
	tzz->SetTextAlign(13);
	tzz->SetTextColor(2);
	rep<<"***************************************************************************************************************************";
	tzz->DrawLatex(2,space[wc],rep.str().c_str());
	rep.str("");
	space[wc]-=spacep;
	rep<<" ERROR >>> CALIBRATION pkt "<<i+1<<" -->CalibTrk"<<(nn+1)%2+1<<" at OBT: "<<OBT[(nn+1)%2]<<" --> cal_flag["<<nn+1<<"]= "<<ctrk.calfl[nn];
	tzz->DrawLatex(2,space[wc],rep.str().c_str());
	rep.str("");
	space[wc]-=spacep;
      }

      if(ctrk.good0[0]==1 && ctrk.good0[1]==1){
	//
	// evaluate the mean value of the sigma and pedestal
	for(Int_t j = 0; j < 3072; j++){
	  sigavtemp[nn][j/256]+=ctrk.dspsig[nn][j];
	  pedavtemp[nn][j/256]+=ctrk.dspped[nn][j];
	}

	for(Int_t ii=0;ii<12;ii++){   
	  pedav[nn][ii]=pedavtemp[nn][ii]/256;  
	  sigav[nn][ii]=sigavtemp[nn][ii]/256;

	  if(pedav[nn][ii]>pedlimsup[nn][ii] || pedav[nn][ii]<pedliminf[nn][ii]) flpedav[nn][ii]=1;  
	  if(sigav[nn][ii]>siglimsup[nn][ii] || sigav[nn][ii]<sigliminf[nn][ii]) flsigav[nn][ii]=1; 

	  if(flpedav[nn][ii]==1){
	    ok=1;
	    if(space[wc]<=3){
	      wc+=1;
	      flcanvas+=1;
	    }
	    c[wc]->cd();
	    tzz->SetTextFont(40);
	    tzz->SetTextSize(0.02);
	    tzz->SetTextAlign(13);
	    tzz->SetTextColor(50);
	    rep<<"********************************************************************************************************************************";
	    tzz->DrawLatex(2,space[wc],rep.str().c_str());
	    rep.str("");
	    space[wc]-=spacep;
	    rep<<"WARNING >>> CALIBRATION pkt "<<i+1<<" -->CalibTrk"<<(nn+1)%2+1<<" at OBT: "<<OBT[(nn+1)%2]<<"-->DSP "<<nn+1<<" -VA1 "<<2*ii+1<<"-"<<2*ii+2<<" --> <PED>= "<<pedav[nn][ii];
	    tzz->DrawLatex(2,space[wc],rep.str().c_str());
	    rep.str("");
	    space[wc]-=spacep;
	  }

	  if(flsigav[nn][ii]==1){
	    ok=1;
	    if(space[wc]<=3){
	      wc+=1;
	      flcanvas+=1;
	    }
	    c[wc]->cd();
	    tzz->SetTextFont(40);
	    tzz->SetTextSize(0.02);
	    tzz->SetTextAlign(13);
	    tzz->SetTextColor(50);
	    rep<<"********************************************************************************************************************************";
	    tzz->DrawLatex(2,space[wc],rep.str().c_str());
	    rep.str("");
	    space[wc]-=spacep;
	    rep<<"WARNING >>> CALIBRATION pkt "<<i+1<<" -->CalibTrk"<<(nn+1)%2+1<<" at OBT: "<<OBT[(nn+1)%2]<<"-->DSP "<<nn+1<<" -VA1 "<<2*ii+1<<"-"<<2*ii+2<<" --> <SIG>= "<<sigav[nn][ii];
	    tzz->DrawLatex(2,space[wc],rep.str().c_str());
	    rep.str("");
	    space[wc]-=spacep;
	  }
	}
      }
    }
    
    if(ok==0 && ctrk.good0[0]==1 && ctrk.good0[1]==1){  
      if(space[wc]<=10){
	wc+=1;
	flcanvas+=1;
      }
      c[wc]->cd();
      tzz->SetTextFont(40);
      tzz->SetTextSize(0.03);
      tzz->SetTextAlign(13);
      tzz->SetTextColor(1);
      rep<<"*********************************** CALIBRATION pkt "<<i+1<<"********************************";
      tzz->DrawLatex(2,space[wc],rep.str().c_str());
      rep.str("");
      space[wc]-=spacep+1;
      rep<<">>>>>>> CalibTrk1 at OBT: "<<OBT[0]<<" ---------> OK ";
      tzz->DrawLatex(2,space[wc],rep.str().c_str());
      rep.str("");
      space[wc]-=spacep+1;
      rep<<">>>>>>> CalibTrk2 at OBT: "<<OBT[1]<<" ---------> OK ";
      tzz->DrawLatex(2,space[wc],rep.str().c_str());
      rep.str("");
      space[wc]-=spacep+1;
      rep<<"*******************************************************************************************";
      tzz->DrawLatex(2,space[wc],rep.str().c_str());
      rep.str("");
      space[wc]-=spacep+1;
    }
  };//end loop on events
  datafile->Close(); 

  //
  // Save output Files
  stringstream nom1,nom2,nom3;

  for(Int_t i=0;i<cnum;i++)
    c[i]->Update();//draw pads in canvas 
    
  for(Int_t fl=0;fl<flcanvas;fl++){
    if(flcanvas==1){
      nom1.str("");
      nom1<<ffile<<"_TrkCalibQLook_BASIC."<<outfile.Data();
      c[fl]->Print(out+nom1.str().c_str());
      nom1.str("");
    }

    if(flcanvas>=2){
      if(!strcmp(outfile.Data(),"ps")||!strcmp(outfile.Data(),"pdf")){
	nom1.str("");
	nom2.str("");
	nom3.str("");
	nom1<<ffile<<"_TrkCalibQLook_BASIC.ps(";
	nom2<<ffile<<"_TrkCalibQLook_BASIC.ps";
	nom3<<ffile<<"_TrkCalibQLook_BASIC.ps)";
	if(fl==0) c[fl]->Print(out+nom1.str().c_str(),"portrait");
	else if(fl==flcanvas-1) c[fl]->Print(out+nom3.str().c_str(),"portrait");
	else c[fl]->Print(out+nom2.str().c_str(),"portrait");
	
      }
      else{
	nom1.str("");
	nom1<<ffile<<"_TrkCalibQLook_BASIC-pag"<<fl+1<<"."<<outfile.Data();
	c[fl]->Print(out+nom1.str().c_str());
      }
    }
  }
  
  if(!strcmp(outfile.Data(),"pdf")&&flcanvas>=2){
    stringstream com;
    com<<"ps2pdf13 "<<out<<ffile<<"_TrkCalibQLook_BASIC.ps "<<out<<ffile<<"_TrkCalibQLook_BASIC.pdf";
    system(com.str().c_str());
    com.str("");
    com<<"rm -f "<<out<<ffile<<"_TrkCalibQLook_BASIC.ps";
    system(com.str().c_str());
    com.str("");
  }
    
  for(Int_t i=0;i<cnum;i++)
    delete c[i];
  
  gROOT->Reset();
  //   printf("... end of packets. \n");
  return;
  
}