//
// Script name:   ND_LEVEL2.c   
// Function name: NDLEVEL2
//
// Author:  Malvezzi-Marcelli
// Version 2.0 - 27/04/2006
//
//

//--- PAMELA classes -------------------------- 
#include <PamelaRun.h>
#include <PscuHeader.h>
#include <PscuEvent.h>
#include <EventHeader.h>
#include <physics/neutronDetector/NeutronEvent.h>
#include <physics/neutronDetector/NeutronRecord.h>
#include <yodaUtility.h>
#include <RegistryEvent.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>
//--- C classes ----------------------------
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <cstring>
#include <stdio.h>
//---- classi per il DB ------
#include <TSQLServer.h>
#include <TSQLResult.h>
#include <TSQLRow.h>

//---- classi per il livello 2 di ND -----
#include <NDLevel2.h>

#define DEBUG 0
using namespace std;

//---------- ND Level2  function --------------------------------------------------
void NDLEVEL2(ULong64_t IDrun, TString outDir, TString processFolder, TString processFile, const char *host, const char *user, const char *psw){

  pamela::NDLevel2 *NDl2 = new pamela::NDLevel2();
  Float_t upperBack=0, bottomBack=0, trigPhysics=0; 

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

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

  //
  //to open connection
  //
  conn = TSQLServer::Connect(host, user, psw); 		
  
  if(!conn){
    printf("ERROR: 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 IdRegRun = 0ULL;
  ULong64_t Ev_Reg_Phys_From = 0ULL;
  ULong64_t Ev_Reg_Phys_To = 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");
    exit(-5);
  }
  IdRegRun = (ULong64_t)atof(row->GetField(0));
  RunHeaderTime = (ULong64_t)atof(row->GetField(1));
  RunTrailerTime = (ULong64_t)atof(row->GetField(2));
  Ev_Reg_Phys_To = (ULong64_t)atof(row->GetField(3));
  Ev_Reg_Phys_From = (ULong64_t)atof(row->GetField(4)); 
  delete result;

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

  row = result->Next();
  if (row == NULL) {
    printf("ERROR: Not result from GL_ROOT \n");
    exit(-6);
  }
  Path << row->GetField(0);
  Name << row->GetField(1); 
  delete result;
  base << Path.str().c_str() <<"/"<<Name.str().c_str();
  conn->Close();
 

  //------------ open file from yoda files-----------------------------
  
  TFile *file = new TFile(base.str().c_str());

  if (!file){ 
    file->Close();
    printf("ERROR: Level 0 file not found  \n");
    exit(-6);
  }

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

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

  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(); 
    exit(-11);
  }
  
  //-------- pamela classes -------------------
  pamela::neutron::NeutronEvent  *ne = 0;
  pamela::neutron::NeutronRecord *nr = 0;
  pamela::EventHeader *eh = 0;
  pamela::PscuHeader *ph = 0;
  pamela::RegistryEvent *reg=0;

  tree->SetBranchAddress("Registry", &reg);
  tree->SetBranchAddress("Neutron", &ne);
  tree->SetBranchAddress("Header", &eh);
  if(!headBr){
    printf("ERROR: No Header TBranch in Level0 file \n");
    file->Close();
    exit(-8);
  }
  if(!regBr){
    printf("ERROR: No Registry TBranch in Level0 file \n");
    file->Close();
    exit(-9);
  }
  
 
  //----- create root file; tree name = NeutronD; number of branch 3 ------------

  TFile *f=0;
  TTree *trNDL2=0;

  fstream myfile;  
  myfile.open(filename.str().c_str());
  if(!myfile){
    f = new TFile(filename.str().c_str(),"recreate");
    trNDL2 = new TTree("NeutronD","ND level2 data");  
    trNDL2->Branch("upperBack", &NDl2->upperBack, "upperBack/F");
    trNDL2->Branch("bottomBack", &NDl2->bottomBack, "bottomBack/F");
    trNDL2->Branch("trigPhysics", &NDl2->trigPhysics, "trigPhysics/F");
   if(!f){
      printf("ERROR: No Level2 input file. \n");
      exit(-600);
    }
  }else{
    f = new TFile(filename.str().c_str(),"update"); 
    if(!f){
      printf("ERROR: Cannot open Level2 input file. \n");
      exit(-601);
    }
    trNDL2 = (TTree*)f->Get("NeutronD");
    if(!trNDL2){
      trNDL2 =  new TTree("NeutronD","ND level2 data");
      trNDL2->Branch("upperBack", &NDl2->upperBack, "upperBack/F");
      trNDL2->Branch("bottomBack", &NDl2->bottomBack, "bottomBack/F");
      trNDL2->Branch("trigPhysics", &NDl2->trigPhysics, "trigPhysics/F");
    }else{
      printf("WARNING: you are re-processing data; \n At this moment this process is not possible. \n ");
      exit(-699);
    }

  }


  //------same variables ------
  Int_t tmpSize = 0;
  
  Float_t yTrig             = 0; 
  Float_t yUpperBackground  = 0; 
  Float_t yBottomBackground = 0;	
 
  //----- Starts the cicle to fill arrays of data,  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);
    NDBr->GetEntry(i);
    tmpSize = ne->Records->GetEntries();
    if (!tmpSize) continue;
    if (ne->unpackError == 1) continue;
    for (Int_t j = 0; j < tmpSize; j++){
      nr = (pamela::neutron::NeutronRecord*)ne->Records->At(j);
      yTrig            = yTrig             + (float)nr->trigPhysics;
      yUpperBackground  = yUpperBackground  + (float)nr->upperBack;
      yBottomBackground = yBottomBackground + (float)nr->bottomBack;
    }
    ph = eh->GetPscuHeader();
    NDl2->upperBack = yUpperBackground;
    NDl2->bottomBack = yBottomBackground;
    NDl2->trigPhysics = yTrig;	     
    
    trNDL2->Fill();        // Fill tree NDLevel2 in the root file

    upperBack = 0;
    yUpperBackground =0;
    bottomBack = 0;
    yBottomBackground =0;
    trigPhysics = 0;
    yTrig=0;	     

  }
  
  file->Close();      // Close file 
  
  f->Write();     // Save the root file	   
  f->Close();
}



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

int main(int argc, char* argv[]){
  ULong64_t IDrun      = 0;
  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: ND_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;
      }
  
  }  

  
  NDLEVEL2(IDrun, outDir, processFolder, processFile, host, user, psw);
   exit(0); 
}

