#include <fstream>
#include <sstream>
#include <string>
#include <math.h>
#include <iostream>
#include <TTree.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 <TGraph.h>
#include <TMultiGraph.h>
#include <TLine.h>
#include <TStyle.h>
#include <TF1.h>
#include <TH1F.h>
#include <TTree.h>
#include <TCanvas.h>
#include <PamLevel2.h>

#include <CaloBragg.h> // ADD HEADER FILE HERE

using namespace std;


//===================================
// global variables
//===================================
Bool_t    DEBUG;
Bool_t    SIMU;
TString   DIR;
TString   LIST;
TString   OPTIONS;
ULong64_t MAXEV;
TString   OUTFILE;

PamLevel2 *pam_event = NULL;
TFile     *outfv = NULL;

bool fillTree   = false;
bool fillHistos = false;


//==========================================
//000000000000000000000000000000000000000000
//==========================================
Int_t Loop(TString ddir,TString list, ULong64_t nmax, TString options, TString outfile){

  
  TH1F *hzeta = new TH1F("hzeta","Zeta Distribution",100,0.,50.);
  
  if(options.Contains("fillTree"))fillTree=true;
  if(options.Contains("fillHisto"))fillHistos=true;
  
  //  -------------------
  //  create output files
  //  -------------------
  TString outfile_t ="";
  //  TString outfile_h ="";
  //  TString outfile_v ="";
  if( outfile.IsNull() ){
    if(!list.IsNull())outfile = list(0,list.Last('.'));	    
    else outfile = "output";	    
  }else{	
    if(outfile.Contains(".root"))outfile = outfile(0,outfile.Last('.'));
  }
  //    if(fillTree){
  outfile_t = outfile;
  outfile_t.Append("-hzeta.root");
  outfv = (TFile*)gROOT->FindObject(outfile_t); 
  if (outfv) outfv->Close();
  outfv = new TFile(outfile_t,"RECREATE");
  if(outfv->IsZombie()){
    cout << "Output file could not be created\n";
    return 1;
  };
  cout << "Created output file: "<<outfv->GetName()<<endl;
  //  --------------------
  //  read input file/list
  //  --------------------
  pam_event = new PamLevel2(ddir,list,options);
  //
  CaloBragg *cn = new CaloBragg(pam_event);  // CREATE CaloBragg OBJECT GIVING PamLevel2 POINTER

  //
  // loop over events
  //
  ULong64_t nevents = pam_event->GetEntries();	
  if(!nmax)nmax = numeric_limits<ULong64_t>::max();	
  if(nevents < nmax)nmax=nevents;  
  cout << endl<<" Start loop over events:  "<< nmax<<endl;
  //    
  for(ULong64_t i=0; i<nmax; i++){
    //
    if ( i%10000 == 0) cout<<i<<endl;
    //
    pam_event->Clear();
    if( pam_event->GetEntry(i) ){ // get the entry
      //
      cn->Print(); // this will simply print on the terminal the determined CaloNuclei values
      //    
      Float_t zeta = cn->Get_lpz();    // here how you can use the "old" dE/dx on the first plane
      printf(" Event number %llu zeta %f \n",i,zeta);
      hzeta->Fill(zeta);

    }   
  };
  pam_event->Clear();
  //
  // save histo to file
  //
  gROOT->cd();
  outfv->cd();
  //
  hzeta->Write();
  outfv->Close();
  //
  printf(" end!\n");
  return 0;
    
}

/////////////////////////////////////////////////////////////////

void usage(){

  cout << "------------------------------------------------------------"<<endl;
  cout << "Loop over events (on one or more Level2-files), applying some selection cuts (defined in My-Selection.cpp), \n";
  cout << "creating output histograms (defined in My-Histos.cpp) and/or trees with selected events. \n \n ";
  cout << "USAGE:"<<endl;
  cout << "-processDir  DIR     -  Level2 data directory \n";
  cout << "-processList LIST    -  list  of files (.txt) or single file (.root) to be analysed \n";
  cout << "-outputFile  PATH    -  name of the output file \n";
  cout << "-NumEvents   XXX     -  number of events to be analysed \n";
  cout << "--debug, -g          -  debug mode \n";
  cout << "--help, -h           -  print this help \n";
  cout << "-options [ options ] -  options: \n";
  cout << "                        fillHistos --> create an output file with histograms  \n";
  cout << "                        fillTree   --> create an output file with trees storing the selected events \n ";
  cout << "                        +(-)ALL    --> inlcude(exclude) all trees and branches \n "   ;
  cout << "                        +(-)TRK1 +(-)TRK2 +(-)CAL1 +(-)CAL2 +(-)TOF +(-)TRG +(-)ND +(-)S4 +(-)ORB --> inlcude(exclude) trees and branches  \n"  ; 
  cout << "------------------------------------------------------------"<<endl;
}
//
int HandleInputPar(int argc, char **argv){

  if(argc>1){
		
    if(!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help") ){
      usage();
      return(1);
    };
    // -----------------------
    // Read input parameters
    // -----------------------  
    DEBUG   = false;
    SIMU   = false;
    DIR     = gSystem->WorkingDirectory();
    LIST    = "";
    OUTFILE = "";
    OPTIONS = "+AUTO fillTree";
    MAXEV   = 0;	
		

    for (int i = 1; i < argc; i++){		
      // -----------------------------------------------------//
      if (!strcmp(argv[i], "-processDir")){
	if (++i >= argc) throw -1;
	DIR = argv[i];
	cout << "processDir "<<DIR<<endl;
	continue;
      }
      // -----------------------------------------------------//
      else if (!strcmp(argv[i], "-processList")){
	if (++i >= argc) throw -1;
	LIST = argv[i];
	cout << "processList "<<LIST<<endl;
	continue;
      }  
      // -----------------------------------------------------//
      else if (!strcmp(argv[i], "-outputFile")){
	if (++i >= argc) throw -1;
	OUTFILE = argv[i];
	cout << "outputFile "<<OUTFILE<<endl;
	continue;
      }  
      // -----------------------------------------------------//
      else if (!strcmp(argv[i], "-NumEvents")){
	if (++i >= argc) throw -1;
	MAXEV = atoi(argv[i]);
	cout << "NumEvents "<<MAXEV<<endl;
	continue;	
      }
      // -----------------------------------------------------//
      else if (!strcmp(argv[i], "-options")){
	if (++i >= argc) throw -1;
	OPTIONS = argv[i];
	if( OPTIONS.Contains("[") ){
	  do{
	    if (++i >= argc) throw -1;
	    OPTIONS.Append(argv[i]);
	  }while(!OPTIONS.Contains("]"));
	}else cout << "wrong option format --> ignoring " << endl;
      }
      // -----------------------------------------------------//
      else if (!strcmp(argv[i], "--debug") || !strcmp(argv[i], "-g")){
	DEBUG = true;
	continue;	
      }
      else if (!strcmp(argv[i], "--simu") || !strcmp(argv[i], "-s")){
	SIMU = true;
	continue;	
      }
      // -----------------------------------------------------//
      else{
	cout << "Unidentified input parameter. Ignored."<< endl;
      };
    };
  }else{
    usage();
    return(1);
  };
  // -----------------------
  // Check input parameters
  // -----------------------  
	
		
  return(0);
	
};
// 

int main(int argc, char **argv)
{
	
  if( HandleInputPar(argc,argv) )return(1);
	
  //    Loop(DIR,LIST,MAXEV,"-ALL+TRK1+TRK2+CAL1+CAL2+TOF+AC",OUTFILE);
  cout << "OPTIONS "<<OPTIONS<<endl;
  Int_t tt = Loop(DIR,LIST,MAXEV,OPTIONS,OUTFILE);
    
  cout << "Back to main - end"<<endl;
    
  return tt;
	
};

