//
// C/C++ headers
//
#include <fstream>
#include <string.h>
//
// ROOT headers
//
#include <TTree.h>
#include <TClassEdit.h>
#include <TObject.h>
#include <TList.h>
#include <TArrayL.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 <TSQLServer.h>
#include <TSQLRow.h>
#include <TSQLResult.h>
#include <TClonesArray.h>
//
// YODA headers
//
#include <PamelaRun.h>
#include <RegistryEvent.h>
#include <physics/trigger/TriggerEvent.h>

// #######################################################################################################################
//
// Calorimeter class CaloProcessing. Do not include CaloLevel2 (it doesn't compile I don't understand why...)
//
#include <CaloProcessing.h>
// #######################################################################################################################



int main(){
  //
  // definizione di variabili 
  //
  TFile *l0File = 0;
  TTree *l0tr = 0;
  TBranch *l0registry = 0;
  TBranch *l0calo = 0;
  ULong64_t atime = 0ULL;
  UInt_t ei = 0;
  UInt_t re = 0;
  Int_t sgnl = 0;
  pamela::RegistryEvent *l0reg=0;
  TSQLServer *dbc = 0;
  dbc = TSQLServer::Connect("mysql://localhost/pamelaprod","anonymous","");

  //  
  // e` importante che CaloProcessing chiami QUI prima di loopare sui run il suo costruttore!
  //
  // #######################################################################################################################
  CaloProcessing *event = new CaloProcessing();
  CaloLevel2 *ca = 0;
  // #######################################################################################################################
  //

  //
  // LOOP ON THE RUNS at some time...
  //

  //
  // now we assume to process run 24 (my run 24 not the one on gundam if any) with 
  //
  ULong64_t runheadtime = 132796435910ULL;
  UInt_t evfrom = 179;
  UInt_t evto = 200;
  //  UInt_t evto = 1354;

  //
  // Open Level0 file and branches
  //
  l0File = new TFile("/wizard3/pamela/samara/filesfromyoda//dw_050318_00100.root");
  if ( !l0File ) {
    printf(" CALORIMETER - ERROR: problems opening  Level0 file\n");
    return(0);
  };
  l0tr = (TTree*)l0File->Get("Physics");
  if ( !l0tr ) {
    printf(" CALORIMETER - ERROR: no Physics tree in Level0 file\n");
    l0File->Close();
    return(0);
  };
  l0registry = l0tr->GetBranch("Registry");
  if ( !l0registry ) {
    printf(" CALORIMETER - ERROR: no Registry branch in Level0 tree\n");
    l0File->Close();
    return(0);
  };
  //
  l0calo = l0tr->GetBranch("Calorimeter");
  if ( !l0calo ) {
    printf(" CALORIMETER - ERROR: no Calorimeter branch in Level0 tree\n");
    l0File->Close();
    return(0);
  };
  //
  l0tr->SetBranchAddress("Registry", &l0reg);




  // #######################################################################################################################
  //
  // Initialize the calorimeter event object, look for the calibration which include the first header
  //  
  printf(" Check for calorimeter calibrations and initialize event object \n");
  event->ProcessingInit(dbc,runheadtime,sgnl,l0tr);
  printf("\n");
  //
  // Check if we have to load parameter files (one time for every run)
  //
  event->ChkParam(dbc,runheadtime); // calorimeter parameter files
  //
  // #######################################################################################################################




  //
  // run over all the events of the run
  //
  printf("\n Ready to start! \n\n");
  //
  for ( re = evfrom; re <= evto; re++){
    //
    l0registry->GetEntry(re);
    //
    // absolute time of this event
    //
    atime = l0reg->absTime;
    //
    // physics events is at entry number ei where
    //
    ei = l0reg->event;
    //



    // #######################################################################################################################
    //
    // create (or clear if existing) a calorimeter level2 object
    //
    ca = new CaloLevel2();
    //
    // check if the calibration we are using is still good, if not load another calibration
    //
    event->ChkCalib(dbc,atime);
    //
    // set this variable to one to be sure to process the event (usually I do not process the event if I don't have a track or a selftrigger event)
    //.          =====>  Notice: the event will NOT be processed if any CRC error in the calorimeter data has occured!!  <=====
    //
    event->clevel1->good2 = 1;
    //
    // Calibrate calorimeter event with registry number "ei" and store output in the two structures that will be passed to fortran routine
    //
    event->Calibrate(ei);
    //
    // Calculate variables common to all tracks (qtot, nstrip, calorimeter fit parameters etc.)
    //
    event->GetCommonVar();
    //
    // Fill common variables
    //
    event->FillCommonVar(ca);
    //
    // Clear structures used to communicate with fortran
    //
    event->ClearStructs();
    //
    // #######################################################################################################################
    //


    //
    // use the output to do something
    //
    printf(" ### Calorimeter tracking output: ### \n");
    printf(" => event %i reg entry %i <= \n",re,ei);
    printf("  ax = %f \n",ca->impx);
    printf("  tanx = %f \n",ca->tanx);
    printf("  ay = %f \n",ca->impy);
    printf("  tany = %f \n",ca->tany);
    printf("  N. point fit x = %i \n",ca->npcfit[0]);
    printf("  N. point fit y = %i \n",ca->npcfit[1]);
    printf("  Variance fit x = %f \n",ca->varcfit[0]);
    printf("  Variance fit y = %f \n",ca->varcfit[1]);
    printf("  Energy assuming interacting electron [GeV]= %f \n",ca->elen);
    printf("  Error on energy [GeV]= %f \n",ca->selen);
    printf(" #################################### \n");
    //
  };



  // #######################################################################################################################
  //
  // this is needed before processing another run!
  //
  event->RunClose();
  //
  // #######################################################################################################################



  //
  // end of the loop over the runs
  //

}
