//
//
//
//
#include <fstream>
#include <sstream>
#include <TTree.h>
#include <TBranch.h>
#include <TClassEdit.h>
#include <TObject.h>
#include <TList.h>
#include <TSystem.h>
#include <TSystemDirectory.h>
#include <TString.h>
#include <TFile.h>
#include <TClass.h>
#include <TCanvas.h>
#include <TH1.h>
#include <TH1F.h>
#include <TH2D.h>
#include <TLatex.h>
#include <TPad.h>
#include <TPaveLabel.h>
#include <TChain.h>
#include <PamelaRun.h>
#include <physics/calorimeter/CalorimeterEvent.h>
#include <CalibCalPedEvent.h>
//

short int FCaloCHECKCRC(TString filename1, TString filename2){
  //
  // open first file
  //
  TFile *File1 = new TFile(filename1.Data());
  TTree *otr1 = (TTree*)File1->Get("Physics");
  TBranch *l0head1 = 0;
  TBranch *l0calo1 = 0;
  //
  pamela::calorimeter::CalorimeterEvent *de1 = 0;   
  pamela::PscuHeader *ph1 = 0;
  pamela::EventHeader *eh1 = 0;
  //
  l0head1 = otr1->GetBranch("Header");
  l0calo1 = otr1->GetBranch("Calorimeter");  
  //
  otr1->SetBranchAddress("Calorimeter", &de1);
  otr1->SetBranchAddress("Header", &eh1);
  //
  // open second file
  //
  TFile *File2 = new TFile(filename2.Data());
  TTree *otr2 = (TTree*)File2->Get("Physics");
  TBranch *l0head2 = 0;
  TBranch *l0calo2 = 0;
  //
  pamela::calorimeter::CalorimeterEvent *de2 = 0;   
  pamela::PscuHeader *ph2 = 0;
  pamela::EventHeader *eh2 = 0;
  //
  l0head2 = otr2->GetBranch("Header");
  l0calo2 = otr2->GetBranch("Calorimeter");  
  //
  otr2->SetBranchAddress("Calorimeter", &de2);
  otr2->SetBranchAddress("Header", &eh2);
  //
  // Define variables
  // 
  Long64_t nevents1    = otr1->GetEntries();
  Long64_t nevents2    = otr2->GetEntries();
  if ( nevents1 < 1 ) {
    printf("The file %s is empty!\n",filename1.Data());
    return(1);
  };
  if ( nevents2 < 1 ) {
    printf("The file %s is empty!\n",filename2.Data());
    return(2);
  };
  //
  printf("\n Processed events: \n\n");
  //
  Int_t c1 = 0;
  Int_t c2 = 0;
  Int_t ecount1 = 0;
  Int_t ecount2 = 0;
  Int_t etime1 = 0;
  Int_t etime2 = 0;
  //
  Int_t frstbad[4];
  Int_t scndbad[4];
  Int_t crcfrstbad[4];
  Int_t crcscndbad[4];
  Int_t crcbothbad[4];
  Int_t frstbadscndgood[4];
  Int_t frstgoodscndbad[4];
  Int_t crcfrstbadscndgood[4];
  Int_t crcfrstgoodscndbad[4];
  Int_t bothbad[4];
  Int_t bothgood[4];
  Int_t samecheck[4];
  Int_t differentcheck[4];
  Int_t samecrc[4];
  Int_t differentcrc[4];
  //
  for ( Int_t s=0; s<4; s++){
    frstbad[s] = 0;
    scndbad[s] = 0;
    crcfrstbad[s] = 0;
    crcscndbad[s] = 0;
    crcbothbad[s] = 0;
    frstbadscndgood[s] = 0;
    frstgoodscndbad[s] = 0;
    crcfrstbadscndgood[s] = 0;
    crcfrstgoodscndbad[s] = 0;
    bothbad[s] = 0;
    bothgood[s] = 0;
    samecheck[s] = 0;
    differentcheck[s] = 0;
    samecrc[s] = 0;
    differentcrc[s] = 0;
  };
  //
  //  for (Int_t i = 0; i < 3000; i++){    
  //
  for (Int_t i = 0; i < max(nevents1,nevents2); i++){    
    //
    if ( i%1000 == 0 && i > 0 ) printf(" %iK \n",i/1000);
    //
    // read from the header of the event the absolute time at which it was recorded
    //
    if ( c1 < nevents1 ){
      l0head1->GetEntry(c1);
      ph1 = eh1->GetPscuHeader(); 
      etime1 = ph1->GetOrbitalTime();
      ecount1 = ph1->GetCounter();
    };
    //
    if ( c2 < nevents2 ){
      l0head2->GetEntry(c2);
      ph2 = eh2->GetPscuHeader(); 
      etime2 = ph2->GetOrbitalTime();
      ecount2 = ph2->GetCounter();
    };
    //
    if ( etime2 == etime1 && ecount2 == ecount1 ){
      if ( c1 < nevents1 ) l0calo1->GetEntry(c1);
      if ( c2 < nevents2 ) l0calo2->GetEntry(c2);
      //
      //
      //
      for ( Int_t s=0; s<4; s++){
	//
	// sum of frstbadscndgood e frstgoodscndbad gives us how many GOOD events we can have merging the two files (not only CRC errors)
	//
	if ( de1->perror[s] != 0 ) frstbad[s]++;
	if ( de2->perror[s] != 0 ) scndbad[s]++;
	if ( de1->perror[s] == 132 ) crcfrstbad[s]++;
	if ( de2->perror[s] == 132 ) crcscndbad[s]++;
	if ( de1->perror[s] != 0 && de2->perror[2] == 0 ) frstbadscndgood[s]++;
	if ( de1->perror[s] == 0 && de2->perror[2] != 0 ) frstgoodscndbad[s]++;
	if ( de1->perror[s] != 0 && de2->perror[2] != 0 ) bothbad[s]++;
	if ( de1->perror[s] == 0 && de2->perror[2] == 0 ) bothgood[s]++;
	//
	if ( de1->perror[s] == 132 && de2->perror[2] == 0 ) crcfrstbadscndgood[s]++;
	if ( de1->perror[s] == 0 && de2->perror[2] == 132 ) crcfrstgoodscndbad[s]++;
	if ( de1->perror[s] == 132 && de2->perror[2] == 132 ){
	  crcbothbad[s]++;
	  if ( de1->calselftrig[0] == de2->calselftrig[0] ) samecheck[s]++;
	  if ( de1->calselftrig[0] != de2->calselftrig[0] ) differentcheck[s]++;
	  if ( de1->calselftrig[1] == de2->calselftrig[1] ) samecrc[s]++;
	  if ( de1->calselftrig[1] != de2->calselftrig[1] ) differentcrc[s]++;
	};
      };
      //
      c1++;
      c2++;
    } else {
      if ( etime2 > etime1 || ecount2 > ecount1 ){
	if ( c1 < nevents1 ){
	  l0calo1->GetEntry(c1);
	  for ( Int_t s=0; s<4; s++){
	    if ( de1->perror[s] != 0 ) frstbad[s]++;
	    if ( de1->perror[s] != 0 ) crcfrstbad[s]++;
	    if ( de1->perror[s] == 0 ) frstgoodscndbad[s]++;
	    if ( de1->perror[s] == 132 ){
	      crcbothbad[s]++;
	      differentcheck[s]++;
	      differentcrc[s]++;
	    };
	  };
	};
	c1++;
      };
      if ( etime1 > etime2 || ecount1 > ecount2 ){
	if ( c2 < nevents2 ){
	  l0calo2->GetEntry(c2);
	  for ( Int_t s=0; s<4; s++){
	    if ( de2->perror[s] != 0 ) scndbad[s]++;
	    if ( de2->perror[s] != 0 ) crcscndbad[s]++;
	    if ( de2->perror[s] == 0 ) frstbadscndgood[s]++;
	    if ( de2->perror[s] == 132 ){
	      crcbothbad[s]++;
	      differentcheck[s]++;
	      differentcrc[s]++;
	    };
	  };
	};
	c2++;
      };
    };
  };
  //
  printf("\n\n");
  printf("##############################################################################\n");
  printf(" File 1: %s \n",filename1.Data());
  printf(" File 2: %s \n",filename2.Data());
  printf("##############################################################################\n");
  for ( Int_t s=0; s<4; s++){
    printf("################################# SECTION %i ##################################\n",s);
    printf(" File 1: number of events........... = %i \n",(int)nevents1);
    printf("       : number of errors........... = %i \n",frstbad[s]);
    printf("       : number of CRC errors....... = %i \n",crcfrstbad[s]);
    printf(" File 2: number of events........... = %i \n",(int)nevents2);
    printf("       : number of errors........... = %i \n",scndbad[s]);
    printf("       : number of CRC errors....... = %i \n",crcscndbad[s]);
    printf(" Events bad in both files........... = %i \n",bothbad[s]);
    printf(" Events good in both files.......... = %i \n",bothgood[s]);
    printf(" Events good in the first and bad in the second file.............. = %i \n",frstgoodscndbad[s]);
    printf(" Events bad in the first and good in the second file.............. = %i \n",frstbadscndgood[s]);
    printf(" Events good in the first and with CRC error in the second file... = %i \n",crcfrstgoodscndbad[s]);
    printf(" Events with CRC error in the first and good in the second file... = %i \n",crcfrstbadscndgood[s]);
    printf(" Events with CRC error in both files.............................. = %i \n",crcbothbad[s]);
    printf(" Events with CRC error in both files and same transmitted CRC..... = %i \n",samecrc[s]);
    printf(" Events with CRC error in both files and different transmitted CRC = %i \n",differentcrc[s]);
    printf(" Events with CRC error in both files and same calculated CRC...... = %i \n",samecheck[s]);
    printf(" Events with CRC error in both files and different calculated CRC. = %i \n",differentcheck[s]);
    printf(" Merging the two files you will have %i good events \n",bothgood[s]+frstgoodscndbad[s]+frstbadscndgood[s]);
    printf("##############################################################################\n");
  };
  printf("\n\n");
  //
  return(0);
  //
}



