// Script name:   S4_LEVEL2.c
// Function name: S4LEVEL2
//
// Author:  Malvezzi-Marcelli
// Version 2.0 - 26/04/2006
//
//

//--- PAMELA classes -------------------------- 
#include <PamelaRun.h>
#include <PscuHeader.h>
#include <PscuEvent.h>
#include <EventHeader.h>
#include <RegistryEvent.h>
#include <CalibS4Event.h>
#include <physics/S4/S4Event.h>
#include <yodaUtility.h>

#include <iostream>
#include <fstream>
#include <cstring>
#include <stdio.h>

//---- standard root classes ---------------
#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 <stdlib.h>
#include <math.h>
//---- classi per il DB ------
#include <TSQLServer.h>
#include <TSQLResult.h>
#include <TSQLRow.h>

//---- classi per il livello 2 di S4 -----
#include <S4Level2.h>



#define DEBUG 0
using namespace std;

//---------- S4 level2 function ----------------------------------------------

void S4LEVEL2(ULong64_t IDrun, TString outDir, TString processFolder, TString processFile, const char *host, const char *user, const char *psw){ 
  
  //----- Create tree, name = S4; number of branch 2 -------------
  pamela::S4Level2 *S4l2 = new pamela::S4Level2();
  Float_t   S4adc=0, S4calibrated=0; 

  stringstream filename;
  filename.str("");
  if(outDir=""){
    filename<<IDrun<<".Level2.root"; 
  }else{
    filename<< outDir <<IDrun <<".Level2.root"; 
  }  

  
  TFile *f=0;
  TTree *trS4L2 =0;

  fstream myfile;
  myfile.open(filename.str().c_str());
  if(!myfile){
    f = new TFile(filename.str().c_str(),"recreate");
    trS4L2 = new TTree("S4","S4 level2 data");  
    trS4L2->Branch("S4calibrated", &S4l2->S4calibrated, "S4calibrated/F");
    trS4L2->Branch("S4adc", &S4l2->S4adc, "S4adc/F");
    if(!f){
      printf("ERROR: No Level2 input file. \n");
      exit(-500);
    }
  }else{
    f = new TFile(filename.str().c_str(),"update");
    if(!f){
      printf("ERROR: Cannot open Level2 input file. \n");
      exit(-501);
    }
    trS4L2 = (TTree *)f->Get("S4");
    if(!trS4L2){
      trS4L2 =  new TTree("S4","S4 level2 data");
      trS4L2->Branch("S4calibrated", &S4l2->S4calibrated, "S4calibrated/F");
      trS4L2->Branch("S4adc", &S4l2->S4adc, "S4adc/F");
    }else{
      printf("WARNING: you are re-processing data; \n At this moment this process is not possible. \n ");
      exit(-599);
    }

  }

  
  //------------------ Quary DB --------------------------------
  //
  // MySQL variables
  //
  
  TSQLServer *conn;	    	
  TSQLResult *result;
  TSQLRow *row;


  //
  //to open connection
  //
  conn = TSQLServer::Connect(host, user, psw); 	

  if(!conn){
    printf("No DB connection (wrong USRN/PWD?). \n");
    exit(-2);
  }

  //
  // Here we query the DB to obtain the informations needed to process the run number "IDrun"
  //
 
  //
  //define variables where to store DB variables (unsigned long long integers, 
  //when set to a number use ULL to store the correct number).
  //
  ULong64_t RunHeaderTime = 0ULL;
  ULong64_t RunTrailerTime = 0ULL;
  ULong64_t IdRegRunHeader = 0ULL;
  ULong64_t Ev_Reg_Phys_From = 0ULL;
  ULong64_t Ev_Reg_Phys_To = 0ULL;
  Double_t  ParamFit0 =  0ULL; 
  Double_t  ParamFit1 =  0ULL; 
  ULong64_t atime = 0ULL;
  Int_t i =0;
  
  //
  // first query: which is the ID of the file which contains the run number "IDrun"?
  // and at what absolute time the run header and run trailer time were recorded?
  // 
  stringstream myquery;
  myquery.str("");
  myquery << "select ID_REG_RUN, RUNHEADER_TIME, RUNTRAILER_TIME, EV_REG_PHYS_TO, EV_REG_PHYS_FROM from GL_RUN where ID= " << IDrun;
  myquery <<";";
  result = conn->Query(myquery.str().c_str());

  row = result->Next();
  if (row == NULL) {
    printf("ERROR: Not result from GL_RUN \n");
    f->Close();
    exit(-5);
  }
  IdRegRunHeader = (ULong64_t)atof(row->GetField(0));
  RunHeaderTime = (ULong64_t)atof(row->GetField(1));
  RunTrailerTime = (ULong64_t)atof(row->GetField(2));
  Ev_Reg_Phys_From = (ULong64_t)atof(row->GetField(4));
  Ev_Reg_Phys_To = (ULong64_t)atof(row->GetField(3)); 
  delete result;

  //
  // second query: which is the value of paramfit relative to the calibration?
  //
  myquery.str("");
  myquery <<"select PARAM_FIT0,PARAM_FIT1 from GL_S4_CALIB where FROM_TIME <"<< RunHeaderTime <<" and TO_TIME >"<<  RunTrailerTime;
  myquery <<";";
  result = conn->Query(myquery.str().c_str());
  
  row = result->Next();
  if (row == NULL) {
    printf("ERROR: Not result from GL_S4_CALIB \n");
    f->Close();
    exit(-502);
  }
  ParamFit0 = atof(row->GetField(0));
  ParamFit1 = atof(row->GetField(1));

  delete result;


  //
  // third query: where can I find the file with the id I have just recovered?
  //
  stringstream Path;
  Path.str("");
  stringstream Name;
  Name.str("");
  stringstream base;
  base.str("");
  myquery.str("");
  myquery << "select PATH, NAME from GL_ROOT where ID=" << IdRegRunHeader ;
  myquery <<";";
  result = conn->Query(myquery.str().c_str());

  
  row = result->Next();
  if (row == NULL) {
    printf("ERROR: Not result from GL_ROOT \n");
    f->Close();
    exit(-6);
  }

  Path << row->GetField(0);
  Name << row->GetField(1); 
  delete result;

  base << Path.str().c_str() <<"/"<<Name.str().c_str();
  



  //---------------Open File from yoda files----------------------------
  TFile  *file  = new TFile(base.str().c_str());
  if (!file){ 
    printf("ERROR: Level 0 file not found  \n");
    file->Close();
    f->Close();
    exit(-6);
  }

  

  //---- Takes the branch of the header and calibration file and matchs the first with S4 file ----------------
  pamela::EventHeader *eh = 0;
  pamela::RegistryEvent *reg=0;
  pamela::S4::S4Event  *s4e = 0;
  pamela::S4::S4Event  *s4Record = 0;
  pamela::PscuHeader *ph = 0;

  TTree *tree = (TTree*)file->Get("Physics");
  TBranch *regBr = tree->GetBranch("Registry");
  TBranch *headBr = tree->GetBranch("Header");
  TBranch *S4Br = tree->GetBranch("S4");

  if(!tree){
    printf("ERROR: No Physics TTree in Level0 file \n");
    file->Close();
    f->Close();
    exit(-7);
  }

  tree->SetBranchAddress("Registry", &reg);
  tree->SetBranchAddress("S4", &s4e);
  tree->SetBranchAddress("Header", &eh); 

  if(!headBr){
    printf("ERROR: No Header TBranch in Level0 file \n");
    file->Close();
    f->Close();
    exit(-8);
  }
  if(!regBr){
    printf("ERROR: No Registry TBranch in Level0 file \n");
    file->Close();
    f->Close();
    exit(-9);
  }
  
  Long64_t nevents = headBr->GetEntries(); 
  Long64_t regevents = regBr->GetEntries();

  if (nevents<=0 || regevents<=0) {
    printf("\n  nevents = %i \n", nevents); 
    printf("\n  regevents = %i \n", regevents);
    printf("ERROR: Level0 file is empty \n");
    file->Close();
    f->Close();
    exit(-11);
  }

  //----- Starts the cicle to fill root file ----------------------
 for (Int_t re = Ev_Reg_Phys_From; re < ((Ev_Reg_Phys_To)+1); re++){
      regBr->GetEntry(re);
      atime = reg->absTime;
      if ( atime > RunTrailerTime || atime < RunHeaderTime  ) continue ;
      i = reg->event;    
      headBr->GetEntry(i);
      S4Br->GetEntry(i);
      if (s4e->unpackError == 1)  continue;      
      S4l2->S4adc = s4e->S4_DATA;
      if ((s4e->S4_DATA) > 31 ){
	S4l2->S4calibrated = ParamFit0*((s4e->S4_DATA)-32)+ParamFit1;
      }else{
	S4l2->S4calibrated = 0;
      }
       
      //cout<<S4l2->S4adc <<"    "<<S4l2->S4calibrated<<"\n";

      trS4L2->Fill();          // Fill tree S4Level2 in the root file

 }

 conn->Close();
 file->Close();      // Close file before go to next one
 f->Write();     // Save the root file
 f->Close();

}


//------------------------- main function --------------------------

int main(int argc, char* argv[]){
  ULong64_t IDrun;
  TString outDir = "./";
  TString processFile = "";
  TString processFolder = "";
  const char *host    = "mysql://localhost/pamelaprod";        //
  const char *user    = "anonymous";                           // MySQL variables
  const char *psw     = "";                                    // 
  

  if (argc < 2){
    printf("ERROR: You have to insert at least the number of run to be processed \n");
    printf("Try '--help' for more information. \n");
    exit(-1);
  }  
  
  if (!strcmp(argv[1], "--help")){
    printf( "Usage: S4_Level2 FILE [OPTION] \n");
    printf( "\t --help                 Print this help and exit \n");
    printf( "\t -IDrun                 The number of run to process \n");
    printf( "\t -outDir                Path where to put the output [default ./] \n");
    printf( "\t -processFolder         Path where to put useful files [default ""] \n");
    printf( "\t -processFile           Name of the input file [default ID_RUN.Level2.root]; \n this parameter is necessary for the re-processing");
    printf( "\t -host                  Name for the host [default = mysql://localhost/pamelaprod] \n");
    printf( "\t -user                  Username for the DB [default = anonymous] \n");
    printf( "\t -psw                   Password for the DB \n");
    exit(-12);
  }

  char* path=argv[1];
  
  for (int i = 2; i < argc; i++){
    
      if (!strcmp(argv[i], "-IDrun")){
	if (++i >= argc){
	  printf( "ERROR: -IDrun needs arguments. \n");
	  printf( "Try '--help' for more information. \n");
	  exit(-1);
	} 
      }
      else{
	IDrun = atoi(argv[i]);
	continue;
      }

      if (!strcmp(argv[i], "-outDir")){
	if (++i >= argc){
	  printf( "ERROR: -outDir needs arguments. \n");
	  printf( "Try '--help' for more information. \n");
	  exit(-3);
	} 
      } else {
	outDir = argv[i];
	continue;
      }  
    
      if (!strcmp(argv[i], "-processFolder")){
	if (++i >= argc){
	  printf( "ERROR: -processFolder needs arguments. \n");
	  printf( "Try '--help' for more information. \n");
	  exit(-3);
	} 
      } else {
	processFolder = argv[i];
	continue;
      }  
    
      if (!strcmp(argv[i], "-processFile")){
	if (++i >= argc){
	  printf( "ERROR: -processFile needs arguments. \n");
	  printf( "Try '--help' for more information. \n");
	  exit(-3);
	} 
      } else {
	processFile = argv[i];
	if((IDrun == 0) && (processFile = "")){
	  printf( "ERROR: -processFile needs arguments. \n");
	  exit(-4);
	}
	continue;
      }  

      if (!strcmp(argv[i], "-host")){
	if (++i >= argc){
	  printf( "ERROR: -host needs arguments. \n");
	  printf( "Try '--help' for more information. \n");
	  exit(-3);
	} 
      }
      else{
	host = argv[i];
	continue;
      }

      if (!strcmp(argv[i], "-user")){
	if (++i >= argc){
	  printf( "ERROR: -user needs arguments. \n");
	  printf( "Try '--help' for more information. \n");
	  exit(-3);
      } 
      } else {
	user = argv[i];
	continue;
      } 

      if (!strcmp(argv[i], "-psw")){
	if (++i >= argc){
	  printf( "ERROR: -psw needs arguments. \n");
	  printf( "Try '--help' for more information. \n");
	  exit(-3);
	} 
      } else {
	psw = argv[i];
	continue;
      }
  }
  
  S4LEVEL2(IDrun, outDir, processFolder, processFile, host, user, psw);
  
  exit(0);
}
