// change the path "/opt/yoda/include/yoda/event/" 
//       relatively to the install yoda directory
#include </opt/yoda/include/yoda/event/PscuHeader.h>
#include </opt/yoda/include/yoda/event/EventHeader.h>
#include </opt/yoda/include/yoda/event/physics/tracker/TrackerEvent.h>
#include </opt/yoda/include/utils/yodaUtility.h>
//
#include "TrkFunctions.cpp"
#include <TPaveText.h>
#include <TLatex.h>
#include <TCanvas.h>
#include <TObjString.h>
#include <TGraph.h>
#include <iostream>
#include <fstream>
#include <TStyle.h>
#include <TString.h>

/**
 *  TrkScanQlook.cpp
 *
 * autor: D.Fedele
 * version 1.0
 * Parameters:
 * 	file - the path to the root file to analyse
 *      outdir - total path of output file 
 *      event - the number of the single event to analyse
 *      DSPprint - the number of a particular DSP to draw (0 don't draw)
 *               
 */

void TrkScanQlook(TString file, TString outdir = "",Int_t event = 1,Int_t DSPprint=0){

  gROOT->Reset();

  // 
  //   obtain information about the data file and select the output file
  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(ffile,fpath,dwpos,dwpos1);
  stringcopy(base,fpath,0,dwpos);

  TString out;
  if(outdir.Length()==0){
    out = base;
  }else{
    out = outdir;
  }
    

  // Define variables 
  Int_t nevents = otr->GetEntries();
  if ( nevents <= 0 ) {
    trackerFile->Close();
    printf("The file is empty, exiting...\n");
    return;
  }

  pamela::tracker::TrackerEvent *trk=0;
  pamela::EventHeader *eh=0;
  pamela::PscuHeader *ph=0;


  // open files
  TFile *trackerFile = new TFile(file);
  if ( !trackerFile ){
    trackerFile->Close();
    printf("No tracker file! \n");
    return;
  }

  //Takes the tree and branches
  TTree *otr   = (TTree*)trackerFile->Get("Physics");

  cout << "\n Number of Entries: " << nevents << endl;
   
  cout<<"Scan of Entry "<<event-1<<"\n"<<endl; 	
	    
  otr->SetBranchAddress("Header",&eh);
  otr->SetBranchAddress("Tracker", &trk);
  otr->GetEntry(event-1);    
  //============================================================================  

  gStyle->SetLabelSize(0.06,"x");
  gStyle->SetLabelSize(0.06,"y");

  gStyle->SetTitleFontSize(0.08);
  gStyle->SetTitleFillColor(10); 
  gStyle->SetTitleFontSize(0.1);
  gStyle->SetTitleOffset(-1,"Y");

  gStyle->SetOptStat(0);
    
  //  draw display area	

  Int_t canvasx=1200;
  Int_t canvasy=900;
  stringstream figsav;
  figsav.str("");
  figsav<<out<<ffile<<"_TrkScanQlook_ev"<<event+1;
  TCanvas *c1 = new TCanvas(figsav.str().c_str(),"TrkQLookSCAN",canvasx,canvasy);
  c1->SetFillColor(10);
  c1->Range(0,0,1,1);
  stringstream fromfile;
  fromfile<<"TrkScanQlook      File: "<<ffile<<"            ---->  Entry  "<<event-1;
  TLatex *t=new TLatex();
  t->SetTextFont(32);
  t->SetTextColor(1);
  t->SetTextAlign(12);
  t->SetTextSize(0.02);
  t->DrawLatex(0.02,0.98,fromfile.str().c_str());

  //  draw pads
  TPad *trkpad[12];          //pad for histos
  TPaveText *trkpadtext[12]; //pad for header
  TH1F *histomax[12];           //histos of max signals
  TH1F *histocomp[12];          //histos of compressed data
  TH1F *histofull[12];          //histos of full data
    
  Double_t posy = 0.95;    // up y-coord - top pads
  Double_t hpad = 0.15;   // pad height
  Double_t posx1=0;          // left  x-coord - pad column 
  Double_t posx2=0;          // right x-coord - pad olumn
  Double_t posx0=0;          //       x-coord - column division
  Double_t wrel = 0.6;     // relative x size of first sub-column
  Double_t marg = 0.004;   // margin among pads


  stringstream title;
  stringstream hid;
  for(Int_t n = 0; n<12; n++){
    if ( (n+1)%2 ) {
      if(n>1)posy = posy-(marg*2+hpad);
      posx1 = marg;
      posx2 = 0.5 - marg;
      posx0 = 0.5*wrel;
    } else {
      posx1 = posx1 + 0.5;
      posx2 = posx2 + 0.5;
      posx0 = posx0 + 0.5;
    };
    
    /* -----------> pad for histograms  */
    trkpad[n] = new TPad("pad"," ",posx1,posy-hpad,posx0-marg,posy,18,0,0);
    trkpad[n]->SetFillColor(19);
    trkpad[n]->SetFrameFillColor(10);
    /* -----------> pad for header dump */
    trkpadtext[n] = new TPaveText((posx0+marg),(posy-hpad),posx2,posy);
    /* -----------> HISTOGRAMS          */

    title<<"DSP "<<n+1;
    hid<<"h"<<n;
    histomax[n] = new TH1F(hid.str().c_str(),title.str().c_str(),3072,0.5,3072.5);
    hid<<"hh"<<n;
    histocomp[n] = new TH1F(hid.str().c_str(),title.str().c_str(),3072,0.5,3072.5);
    hid<<"hhh"<<n;
    histofull[n] = new TH1F(hid.str().c_str(),title.str().c_str(),3072,0.5,3072.5);
    title.str("");
    hid.str("");
  }                     //end loop on views

  // = = = = = = = = = = = = = = = = = = = = = = = = =
  //  create header dump retrieving event info
  // = = = = = = = = = = = = = = = = = = = = = = = = =
  Int_t ndsp=0;
  stringstream message;

  Double_t whistomax[3072];
  Double_t whisto[3072];
  Double_t whistocomp[3072];
  Double_t whistofull[3072];

  //=============================================
  //      transmitted words
  Int_t word = 0;
  Int_t iword = 0;
  Int_t TOTDATAlength_check = 0;    
  Int_t ii=0,ifull[12],icomp[12],imax[12],nn=0;    
  trkword thisword;

  Int_t address,ladder,adcvalue;

  for(Int_t n = 0; n<12; n++){
    
    ndsp = trk->DSPnumber[n];
    nn = ndsp-1;
    ifull[nn]=0;
    icomp[nn]=0;
    imax[nn]=0;
	
    /*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*
     *
     * Write event LEVEL0 report
     *
     *.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*/

    trkpadtext[nn]->SetTextFont(40);
    trkpadtext[nn]->SetFillColor(33);
    trkpadtext[nn]->SetTextSize(0.012);
    trkpadtext[nn]->SetTextAlign(13);

    trkpadtext[nn]->AddText(" ");
    message<<"DAQ mode  --------> "<<trk->DAQmode[n];
    trkpadtext[nn]->AddText(message.str().c_str());
    message.str("");
    message<<"Event number  --------> "<<trk->eventn[n];
    trkpadtext[nn]->AddText(message.str().c_str());
    message.str("");
    message<<"13-bit words --------> "<<trk->DATAlength[n];
    trkpadtext[nn]->AddText(message.str().c_str());
    message.str("");
    if (!(nn%2)&&trk->signcluster[n][0]!=0) message<<"L1  add:  "<<trk->addrcluster[n][0]<<" - sign: "<<1024-(trk->signcluster[n][0]);
    else message<<"L1  add:  "<<trk->addrcluster[n][0]<<" - sign: "<<(trk->signcluster[n][0]);
    trkpadtext[nn]->AddText(message.str().c_str());
    message.str("");
    if (!(nn%2)&&trk->signcluster[n][1]!=0) message<<"L2  add:  "<<trk->addrcluster[n][1]<<" - sign: "<<1024-(trk->signcluster[n][1]);
    else message<<"L2  add:  "<<trk->addrcluster[n][1]<<" - sign: "<<trk->signcluster[n][1];
    trkpadtext[nn]->AddText(message.str().c_str());
    message.str("");
    if (!(nn%2)&&trk->signcluster[n][2]!=0) message<<"L3  add:  "<<trk->addrcluster[n][2]<<" - sign: "<<1024-(trk->signcluster[n][2]);
    else message<<"L3  add:  "<<trk->addrcluster[n][2]<<" - sign: "<<trk->signcluster[n][2];
    trkpadtext[nn]->AddText(message.str().c_str());
    message.str("");
    message<<"NCLUST "<<trk->nclust[n]<<"    CUTC "<<trk->cutc[n]<<"   CUTCL "<<trk->cutcl[n];
    trkpadtext[nn]->AddText(message.str().c_str());
    message.str("");
    message<<"Comp. time "<<trk->compressiontime[n]<<" x 0.051ms = "<<0.051*trk->compressiontime[n]<<" ms";
    trkpadtext[nn]->AddText(message.str().c_str());
    message.str("");
    trkpadtext[nn]->AddText(" ");
    message<<"FL1-6 -->  "<<trk->fl1[n]<<" "<<trk->fl2[n]<<" "<<trk->fl3[n]<<" "<<trk->fl4[n]<<" "<<trk->fl5[n]<<" "<<trk->fl6[n]<<" FC "<<trk->fc[n];
    trkpadtext[nn]->AddText(message.str().c_str());
    message.str("");
    trkpadtext[nn]->AddText(" ");
    trkpadtext[nn]->AddLine(0,0,0,0);
    message<<"PNum "<<trk->pnum[n]<<" - BId "<<trk->bid[n]<<"       ALARM  "<<trk->alarm[n];
    trkpadtext[nn]->AddText(message.str().c_str());
    message.str("");
    message<<"Cmd "<<trk->cmdnum[n]<<" --- Answer length "<<trk->aswr[n]<<" byte";
    trkpadtext[nn]->AddText(message.str().c_str());
    message.str("");
    trkpadtext[nn]->AddText(" ");
	
    TOTDATAlength_check = TOTDATAlength_check + trk->DATAlength[n];

    /*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*
     *
     * Plot event LEVEL0 histo
     *
     *.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*/

    //=============================================

    for(Int_t i = 0; i< 3072; i++){
      whistomax[i] = -200;
      whistocomp[i] = -200;
      whistofull[i] = -200;
      whisto[i] = -200;
    }

    //      ===============
    //      trasmitted data
    //      ===============

    address = 0;
    ladder = 1;
    for(Int_t i = 0; i < trk->DATAlength[n] ; i++){
      word = trk->TrackerData.At(iword);	    
      thisword = datadecode(word);
      iword++;
      switch (thisword.type){
	    
      case 0:  //ADC value
	whisto[address] = thisword.decode;
	address++;    
	//	cout << "    adr " << address << "\n"; 
	break;

      case 1:  //address
	address = 1024*(ladder-1) + thisword.decode;
	//	cout << "    adr " << address << "\n";
	break;

      case 2:  //end-of-ladder
	ladder = thisword.decode;
	//		cout << "Ladder " << ladder << "\n"; 
	if(ladder==3){
	  //                  end of compressed data - FILL HISTO
	  //cout << ">>> COMPRESSED data" << "\n";
	  for(ii = 0; ii < 3072; ii++){
	    whistocomp[ii]=whisto[ii];
	    whisto[ii] = -200;
	  }
	  address = 0;
	  ladder = 1;		    
	}else if(ladder==6){
	  //                  end of full data - FILL HISTO
	  //cout << ">>> FULL data" << "\n";
	  for(ii = 0; ii < 3072; ii++){
	    whistofull[ii]=whisto[ii];
	    whisto[ii] = -200;
	  }
	  address = 0;
	  ladder = 1;
	}else{		
	  if(ladder>3)	ladder=ladder-3;
	  address= ladder*1024;		
	  ladder = ladder + 1;	
	}
      }    
    }    
	

    //      ===============
    //      maximum signals
    //      ===============
    if(trk->signcluster[nn][0]!=0) whistomax[   0+(int)trk->addrcluster[nn][0]] = whistocomp[   0+(int)trk->addrcluster[nn][0]];
    if(trk->signcluster[nn][1]!=0) whistomax[1024+(int)trk->addrcluster[nn][1]] = whistocomp[1024+(int)trk->addrcluster[nn][1]];
    if(trk->signcluster[nn][2]!=0) whistomax[2048+(int)trk->addrcluster[nn][2]] = whistocomp[2048+(int)trk->addrcluster[nn][2]];

    for(Int_t i = 0; i < 3072; i++){
      if(whistomax[i]>-200) imax[nn]=1;
      if(whistocomp[i]>-200) icomp[nn]=1;
      if(whistofull[i]>-200) ifull[nn]=1;
      histomax[nn]->Fill((Float_t)i,whistomax[i]);
      histocomp[nn]->Fill((Float_t)i,whistocomp[i]);
      histofull[nn]->Fill((Float_t)i,whistofull[i]);
    }
    c1->cd();           
    trkpadtext[nn]->Draw();
    trkpad[nn]->Draw();
    trkpad[nn]->cd();

    histocomp[nn]->GetYaxis()->SetRangeUser(-500,4500);
    histocomp[nn]->SetLineStyle(1);
    histocomp[nn]->SetLineColor(38);
    histocomp[nn]->SetFillColor(38);
    histocomp[nn]->SetLineWidth(1);
    if(icomp[nn]==1) histocomp[nn]->Draw("9b");

    histofull[nn]->SetLineColor(40);
    histofull[nn]->SetFillColor(40);
    histofull[nn]->SetLineWidth(1);
    histofull[nn]->SetLineStyle(2);
    if(ifull[nn]==1) histofull[nn]->Draw("9bsame][");

    histomax[nn]->SetLineColor(2);
    histomax[nn]->SetLineWidth(1);
    histomax[nn]->SetLineStyle(3);
    if(imax[nn]==1) histomax[nn]->Draw("same][");
    c1->Update();
  
  }//end loop on views
  
  if(DSPprint!=0){
    if(DSPprint<=12){
      stringstream figsav;
      figsav.str("");
      figsav<<out<<ffile<<"_TrkScanQlook_ev"<<event+1<<"-DSP"<<DSPprint;
      TCanvas *c2 = new TCanvas(figsav.str().c_str(),"TrkQLookSCAN DSP",canvasx,canvasy);
      c2->SetFillColor(10);
      c2->Range(0,0,1,1);
      stringstream fromfile;
      fromfile<<"TrkScanQlook      File: "<<ffile<<"            ---->  Entry  "<<event<<"   ------> DSP "<<DSPprint;
      TLatex *t=new TLatex();
      t->SetTextFont(32);
      t->SetTextColor(1);
      t->SetTextAlign(12);
      t->SetTextSize(0.02);
      t->DrawLatex(0.02,0.98,fromfile.str().c_str());
      
      c2->cd();
      gStyle->SetTitleFontSize(0.022);
      histocomp[DSPprint-1]->GetXaxis()->SetLabelSize(0.015);
      histocomp[DSPprint-1]->GetYaxis()->SetLabelSize(0.015);
      if(icomp[DSPprint-1]==1) histocomp[DSPprint-1]->Draw("9b");
      if(ifull[DSPprint-1]==1) histofull[DSPprint-1]->Draw("9bsame][");
      if(imax[DSPprint-1]==1) histomax[DSPprint-1]->Draw("same][");
      c2->Update();
    }
    else if(DSPprint>12)
      printf("The DSP number has to be between 1 and 12\n");
  }
    
  return;
  
}