/**
 * FTrkQLook_BASIC.cxx
 *
 * autor: D.Fedele
 * version v1r12
 * Parameters:
 * 	file - the data file to analyze
 *      fromevent - first event to analyze
 *      toevent - last event to analyze
 *      outdir - total path of output file 
 * 	outfile - extension of output file (pdf,ps,gif,jpg)
 * 
 */
//
#include <TPaveText.h>
#include <TLatex.h>
#include <TCanvas.h>
#include <TGraph.h>
#include <TStyle.h>
#include <TFile.h>
#include <TTree.h>
#include <TArrow.h>
#include <TAxis.h>
#include <TROOT.h>
#include <cstdlib>
#include <sys/stat.h>
//
#include <physics/tracker/TrackerEvent.h>
#include <PscuHeader.h>
#include <EventHeader.h>
#include <RunHeaderEvent.h>
#include <EventCounter.h>
#include <PacketType.h>
//
#define MAXSTORAGE 50000

void FTrkQLook_BASIC(TString file,Int_t fromevent,Int_t toevent, TString outdir,TString outfile)
{   
  // 
  //   obtain information about the data file and select the output dir
  Int_t dwpos = file.Last('/');
  Int_t dwpos1 = file.Last('.');
  TString base,ffile ;
  ffile=file(dwpos+1,dwpos1-(dwpos+1));
  if(dwpos>0) base=file(0,dwpos);

  TString out;
  if(outdir.Length()==0){
    out = base;
  }else{
    out = outdir;
  }
  if(out.Last('/')+1<out.Length()) out+="/";
   
  //
  // inizialise the variables and open the file
  pamela::tracker::TrackerEvent *te=0;
  pamela::EventHeader *eh=0,*eH=0,*ceh=0;
  pamela::RunHeaderEvent *reh=0;
  pamela::PscuHeader *ph=0,*pH=0;
  pamela::EventCounter *cod=0;

  pamela::PacketType *pctp=0;

  TFile *datafile = new TFile(file);
  TTree *otr 	      = (TTree*)datafile->Get("RunHeader");
  otr->SetBranchAddress("Header",&eH);
  otr->SetBranchAddress("RunHeader",&reh);
  TTree *tr 	      = (TTree*)datafile->Get("Physics");
  tr->SetBranchAddress("Tracker",&te);
  tr->SetBranchAddress("Header",&eh);
  TTree *ctr 	      = (TTree*)datafile->Get("CalibTrk1");
  ctr->SetBranchAddress("Header",&ceh);
  
  Long64_t neventC = ctr->GetEntries();
  Long64_t nevent = tr->GetEntries();
  Long64_t neventH = otr->GetEntries();
  Int_t minevent=0;
  Int_t maxevent=0; 

  printf("Number of total events: %lld\nNumber of total header events: %lld\n",nevent,neventH);
  printf("Number of calibration events: %lld\n",neventC);

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

  //
  // other variables definitions
  stringstream oss,fromfile,isfile;
  //
  // information about the RunHeader
  ULong_t HOBT[neventH];
  Int_t trk_cal_us[neventH];
  for (Int_t vi=0; vi<neventH;vi++){
    HOBT[vi]=0;
    trk_cal_us[vi]=0;
  }
  
  //
  // information about RunHeader
  Int_t countnboot=1;
  for (Int_t ev=0; ev<neventH; ev++){
    otr->GetEntry(ev);
    pH = eH->GetPscuHeader();
    HOBT[ev]= pH->GetOrbitalTime();
    trk_cal_us[ev]=reh->TRK_CALIB_USED;
    if((HOBT[ev]<HOBT[ev-1]) && ev>0)
      countnboot+=1;
  }
  countnboot+=(Int_t)(2*nevent/MAXSTORAGE);
  //  printf("\ncountnboot=%d\n",countnboot);

  //
  // information about calibration OBT
  ULong_t COBT[neventC];
  for (Int_t vi=0; vi<neventC;vi++){
    COBT[vi]=0;
  }
  for (Int_t ev=0; ev<neventC; ev++){
    ctr->GetEntry(ev);
    pH = ceh->GetPscuHeader();
    COBT[ev]= pH->GetOrbitalTime();
  }

  //
  // Style options
  gStyle->SetLabelSize(0.06,"x");
  gStyle->SetLabelSize(0.06,"y");
  gStyle->SetStatFontSize(0.075);
  gStyle->SetOptStat(10);
  gStyle->SetFillColor(10);  
  gStyle->SetTitleFontSize(0.1);
  gStyle->SetTitleFillColor(10);
  gStyle->SetTitleOffset(0.8,"y");
  gStyle->SetTitleOffset(0.9,"x");
  gStyle->SetTitleSize(0.06,"y");
  gStyle->SetTitleSize(0.055,"x");

  //***************************************************************************************
  // LOOP on each event
  //***************************************************************************************

  if (fromevent!=0)
    printf("\n Scan of events from %i to %i ... \n",minevent,maxevent-1);
  else 
    printf("\n Scan of events from %i to %i ... \n",minevent+1,maxevent);
  
 
  Int_t minev=minevent,maxev=maxevent,hin=0,hfin=0,cin=0,cfin=0;
  TPad *pad[12][countnboot];
  TGraph *dataletime[12][countnboot],*dataletime1[12][countnboot];
  TCanvas *DataTimeCanv[countnboot];
  for(Int_t ii=0; ii<countnboot;ii++){
    fromfile<<"FTrkQLook_BASIC      File: "<<ffile;
    isfile<<"DATALENGTH vs. OBT   pag"<<ii+1;
    DataTimeCanv[ii]=new TCanvas(isfile.str().c_str(),isfile.str().c_str(),900,1200);
    DataTimeCanv[ii]->SetFillColor(10);
    DataTimeCanv[ii]->Range(0,0,100,100);

    TLatex *t=new TLatex();
    t->SetTextFont(32);
    t->SetTextColor(1);
    t->SetTextAlign(12);
    t->SetTextSize(0.02);
    t->DrawLatex(2.,98.7,fromfile.str().c_str());
    TLatex *t1=new TLatex();
    t1->SetTextFont(32);
    t1->SetTextColor(1);
    t1->SetTextAlign(12);
    t1->SetTextSize(0.02);
    t1->DrawLatex(70.,98.7,isfile.str().c_str());
    fromfile.str("");
    isfile.str("");
    
    fromfile<<"D = Default Calibration";
    isfile<<"O = OnLine Calibration";
    t->SetTextColor(6);
    t->SetTextSize(0.018);
    t->DrawLatex(70.,97.,fromfile.str().c_str());
    t->SetTextColor(3);
    t->DrawLatex(70.,96.,isfile.str().c_str());
    fromfile.str("");
    isfile.str("");

    fromfile<<"The green arrow (if present) points out the time of the online calibration";
    t->DrawLatex(7.,96.,fromfile.str().c_str());
    fromfile.str("");

    //*************************************************************************************
    //book pads and histos
    //***************************************************************************************
 
    
    Float_t posy = 0.95;    // up y-coord - top pads
    Float_t hpad = 0;   // pad height
    Float_t posx1=0;          // left  x-coord - pad column
    Float_t posx0=0;          //       x-coord - column division
    Float_t wrel = 0;     // relative x size of first sub-column
    Float_t marg = 0.004;   // margin among pads
    
    hpad = (posy-marg*11)/6;
    wrel = (1-marg*4)/2;
    stringstream title;
    stringstream hid;
    
    for(Int_t n = 0; n<12; n++) {
      if ( (n+1)%2==1 ) {
	if(n>1) posy = posy-(marg*2+hpad);
	posx1 = marg;
	posx0 = posx1 + wrel;
      }
      else {
	posx1 = posx0 + 2*marg;
	posx0 = posx1 + wrel;
      }
      
      /* -----------> pad for histograms  */
      oss<<"pad"<<n*100+ii;
      pad[n][ii]=new TPad(oss.str().c_str()," ",posx1,posy-hpad,posx0,posy,18,0,0);
      oss.str("");
    };            

    TLine li;
    li.SetLineColor(1);
    li.SetLineStyle(1);
    li.SetLineWidth(1);

    TArrow ar;
    ar.SetLineColor(3);
    stringstream calus;

    TLatex *t2=new TLatex();
    t2->SetTextFont(32);
    t2->SetTextColor(1);
    t2->SetTextAlign(13);
    t2->SetTextSize(0.08);

    Int_t i=0;
    ULong_t  x[MAXSTORAGE], xb[MAXSTORAGE];
    Float_t yyd[MAXSTORAGE][12],yyb[MAXSTORAGE][12];
    Int_t countbad[12];
    Float_t perc=0;
    Double_t xMIN=0.,xMAX=0.;
    for (Int_t n=0; n<12 ; n++)
      countbad[n]=0;

    //
    // obtain values of the datalenght
    for (Int_t ev=minev; ev<maxevent; ev++){
      tr->GetEntry(ev);
      ph = eh->GetPscuHeader();
      cod = eh->GetCounter();
      
      if(ev==minev){
	if(cod->Get(pctp->CalibTrk1)>0) cin=cod->Get(pctp->CalibTrk1)-1;
	else cin=cod->Get(pctp->CalibTrk1);
	if(cin==cfin-1) cin+=1;

	if(cod->Get(pctp->RunHeader)>0) hin=cod->Get(pctp->RunHeader)-1;
	else hin=cod->Get(pctp->RunHeader);
	if(hin==hfin-1) hin+=1;
      }

      if(ev==maxevent-1) maxev=maxevent-1;

      if(((ULong_t)ph->GetOrbitalTime()<x[ev-minev-1] && ev-minev!=0) || ev-minev==MAXSTORAGE){
	maxev=ev;
	break;
      }
      else{
	cfin=cod->Get(pctp->CalibTrk1);
	hfin=cod->Get(pctp->RunHeader);
	x[(ev-minev)]= ph->GetOrbitalTime();
	i=0;
      
	for (Int_t n=0; n<12 ; n++){
	  i=te->DSPnumber[n]-1; 
	  if(i>=0){
	    if(i<12){
	      yyb[countbad[i]][i]=0;
	      xb[countbad[i]]= 0;
	      
	      yyd[(ev-minev)][i]=te->DATAlength[n];
	      if(i==6){
		if(yyd[(ev-minev)][i]>1500){
		  if(yyd[(ev-minev)][i]<3075){
		    yyb[countbad[i]][i]= yyd[(ev-minev)][i];
		    xb[countbad[i]]= x[(ev-minev)];
		    countbad[i]+=1;
		  }
		}
	      }
	      else{
		if(yyd[(ev-minev)][i]>750){
		  if(yyd[(ev-minev)][i]<3075){
		    yyb[countbad[i]][i]= yyd[(ev-minev)][i];
		    xb[countbad[i]]= x[(ev-minev)];
		    countbad[i]+=1;
		  }
		}
	      }
	    }
	  }
	}	
      }
    }
    
    //
    // define limit for the Xaxis of the graphs

    xMAX=x[maxev-minev-1]+(x[maxev-minev-1]-x[0])/10;
    if(xMAX>1000000) xMIN=x[0]-(x[maxev-minev-1]-x[0])/10;
    if(xMAX<1000000 || xMIN<0) xMIN=0.;     
    if(xMIN==xMAX) xMIN=x[0] * x[0]/xMAX;     
        
    
    //
    // Draw Histos
    for (Int_t n=0; n<12 ; n++){ 
    
      Double_t yd[maxev-minev],ybd[maxev-minev];
      Double_t xd[maxev-minev],xbd[maxev-minev];

      for(Int_t v=0;v<maxev-minev;v++){
	yd[v]=(Double_t)yyd[v][n];
	ybd[v]=(Double_t)yyb[v][n];
	xd[v]=(Double_t)x[v];
	xbd[v]=(Double_t)xb[v];
      }
      
      if(xMAX<1000000){
	xd[maxev-minev-1]=0;
	yd[maxev-minev-1]=0.;
      }

      if((maxev-minev)>1000){
	perc=(countbad[n]*100)/(maxev-minev);
	if(perc>10) pad[n][ii]->SetFillColor(2);
	else  pad[n][ii]->SetFillColor(10);
	
      }
      else{
	if(countbad[n]>=100) pad[n][ii]->SetFillColor(2);
	else pad[n][ii]->SetFillColor(10);
      }

      oss<<"DSP  "<<n+1;
      DataTimeCanv[ii]->cd();
      pad[n][ii]->SetFrameFillColor(10);
      pad[n][ii]->Draw();
      pad[n][ii]->cd();
      dataletime[n][ii]= new TGraph((maxev-minev),xd,yd);
      if(maxev-minev==1) dataletime[n][ii]->GetXaxis()->SetNdivisions(-501);
      dataletime[n][ii]->SetTitle(oss.str().c_str());
      dataletime[n][ii]->GetXaxis()->SetTitle("OBT (ms)");
      dataletime[n][ii]->GetXaxis()->CenterTitle();
      dataletime[n][ii]->GetXaxis()->SetRangeUser(xMIN,xMAX);
      dataletime[n][ii]->GetYaxis()->SetTitle("datalength (Word 13 bit)");
      dataletime[n][ii]->GetYaxis()->CenterTitle();
      if(i==6) dataletime[n][ii]->GetYaxis()->SetRangeUser(0,4500);
      else dataletime[n][ii]->GetYaxis()->SetRangeUser(0,4000);
      dataletime[n][ii]->SetMarkerStyle(21);
      if((maxev-minev)<50) dataletime[n][ii]->SetMarkerSize(0.5);
      else dataletime[n][ii]->SetMarkerSize(0.1);
      dataletime[n][ii]->SetMarkerColor(4);
      dataletime[n][ii]->Draw("ap");


      if((maxev-minev)>1000 && perc>10){
	dataletime1[n][ii]= new TGraph(countbad[n],xbd,ybd);
	dataletime1[n][ii]->SetMarkerStyle(21);
	dataletime1[n][ii]->SetMarkerSize(0.1);
	dataletime1[n][ii]->SetMarkerColor(2);
	dataletime1[n][ii]->Draw("psame");
      }
      else if((maxev-minev)<1000 && countbad[n]>=100){
	dataletime1[n][ii]= new TGraph(countbad[n],xbd,ybd);
	dataletime1[n][ii]->SetMarkerStyle(21);
	if((maxev-minev)<50) dataletime1[n][ii]->SetMarkerSize(0.5);
	else dataletime1[n][ii]->SetMarkerSize(0.1);
	dataletime1[n][ii]->SetMarkerColor(2);
	dataletime1[n][ii]->Draw("psame");
      }
      li.SetLineColor(1);
      li.SetLineStyle(1);
      li.SetLineWidth(1);
      if(i!=6) li.DrawLine(xMIN,750,xMAX,750);
      else li.DrawLine(xMIN,1500,xMAX,1500);
      li.DrawLine(xMIN,3075,xMAX,3075);

      li.SetLineColor(12);
      li.SetLineStyle(4);
      li.SetLineWidth(1);
      for(Int_t j=hin;j<hfin;j++){
	if(i==6)  li.DrawLine(HOBT[j],0.,HOBT[j],4500.);
	else li.DrawLine(HOBT[j],0.,HOBT[j],4000.);
	if(trk_cal_us[j]==104){
	  calus<<"D";
	  t2->SetTextColor(6);
	  if(i==6)  t2->DrawLatex(HOBT[j],4350.,calus.str().c_str());
	  else t2->DrawLatex(HOBT[j],3850.,calus.str().c_str());
	  calus.str("");
	}	
	else{
	  calus<<"O";
	  t2->SetTextColor(3);
	  if(i==6) t2->DrawLatex(HOBT[j],4350.,calus.str().c_str());
	  else t2->DrawLatex(HOBT[j],3850.,calus.str().c_str());
	  calus.str("");
	}
      }
      for(Int_t j=cin;j<cfin;j++){
	if(i==6)  ar.DrawArrow(COBT[j],1700.,COBT[j],2700.,0.01,"<");
	else ar.DrawArrow(COBT[j],1000.,COBT[j],2000.,0.01,"<");
      }
            
      oss.str("");
      DataTimeCanv[ii]->Update();
    }
  
    minev=maxev;
    if(maxev==maxevent-1) {
      countnboot=ii+1;
      break;
    }
  }
  printf("... end of packets. \n");

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

  for(Int_t fl=0;fl<countnboot;fl++){
    if(countnboot==1){
      nom1<<ffile<<"_FTrkQLook_BASIC."<<outfile.Data();
      DataTimeCanv[fl]->Print(out+nom1.str().c_str());
      nom1.str("");
    }

    if(countnboot>=2){
      if(!strcmp(outfile.Data(),"ps") || !strcmp(outfile.Data(),"pdf")){
	nom1.str("");
	nom2.str("");
	nom3.str("");
	nom1<<ffile<<"_FTrkQLook_BASIC.ps(";
	nom2<<ffile<<"_FTrkQLook_BASIC.ps";
	nom3<<ffile<<"_FTrkQLook_BASIC.ps)";
	if(fl==0) DataTimeCanv[fl]->Print(out+nom1.str().c_str(),"portrait");
	else if(fl==countnboot-1) DataTimeCanv[fl]->Print(out+nom3.str().c_str(),"portrait");
	else DataTimeCanv[fl]->Print(out+nom2.str().c_str(),"portrait");
	
      }
      else{
	nom1.str("");
	nom1<<ffile<<"_FTrkQLook_BASIC-pag"<<fl+1<<"."<<outfile.Data();
	DataTimeCanv[fl]->Print(out+nom1.str().c_str());
      }
    }
  }
  
  //
  // Convert ps to pdf if required
  if(!strcmp(outfile.Data(),"pdf") && countnboot>=2){
    stringstream com;
    com<<"ps2pdf13 "<<out<<ffile<<"_FTrkQLook_BASIC.ps "<<out<<ffile<<"_FTrkQLook_BASIC.pdf";
    system(com.str().c_str());
    printf("\n---> ps file converted in pdf format!\n");
    com.str("");
    com<<"rm -f "<<out<<ffile<<"_FTrkQLook_BASIC.ps";
    system(com.str().c_str());
    printf("---> ps file removed!\n\n");
    com.str("");
   }    
  
  datafile->Close();
  gROOT->Reset();
  return;
}
