//
//- Emiliano Mocchiutti
//
//   CaloCALIBSCAN.c      version 1.05  (2005-11-17)
//
//   The only input needed is 
//
//   Changelog:
//
//   1.04 - 1.05  (2005-11-17): compiled!
//
//   1.03 - 1.04  (2005-08-15): 64 bit arch bugs fixed.
//
//   1.02 - 1.03  (2005-08-04): small bugs fixed.
//
//   1.01 - 1.02  (2005-07-21): don't load anymore yodaUtility.c, use instead clone routines.
//
//   1.00 - 1.01  (2005-07-12): small changes for compilation.
//
//   0.90 - 1.00  (2005-06-28): Working. Many changes.
//
//   0.90         (2005-04-14): Created and partially working.
//
#include <fstream>
#include <sstream>
#include <string>
#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>
#if !defined (__CINT__)				
#include <event/PamelaRun.h>
#include <event/physics/calorimeter/CalorimeterEvent.h>
#include <event/physics/trigger/TriggerEvent.h>
#include <event/CalibCalPedEvent.h>
#include <caloclasses.h>
#endif
#include <CaloFunctions.h>

short int CaloCALIBSCAN(TString Filename, TString flist=""){
    gROOT->GetListOfCanvases()->Delete("a");
    gDirectory->GetList()->Delete();
#if defined (__CINT__)	
    emicheckLib();
    stringstream llib;
    const char *pamlib = gSystem->ExpandPathName("$PAM_LIB");
    llib << pamlib << "/caloclasses_h.so"; 
    gSystem->Load(llib.str().c_str());
#endif
    TString calcalib;
    struct Calib calib;
    //
    stringstream file5;
    const char *pam_calib=gSystem->Getenv("PAM_CALIB");
    file5.str("");
    file5 << pam_calib << "/CaloCALIBdata.root";
    //    sprintf(file5,"%s/CaloCALIBdata.root",pam_calib);  
    //file5 = Form("%s/CaloCALIBdata.root",pam_calib);
    //
    Int_t nfile = 0;
    Int_t calibex = 0;
    Int_t fileup = 0;
    if ( flist != "" ){
	printf("\n You have given an input file list \n\n Files: \n");
	ifstream in;
	in.open(flist, ios::in);
	char ctime[20];
	while (1) {       
	    in >> ctime;
	    if (!in.good()) break;
	    printf(" File number %i = %s \n",nfile+1,ctime);	    
	    nfile++;
	    //	    if ( nfile > 499 ) {
	    //	printf(" No more than 500 files please! \n ");
	    //	return;
	    //};
	};
	in.close();
	if ( !nfile ) {
	    printf("\n\n The list is empty, exiting... \n\n");	    
	    return(0);
	};
    } else {
    	nfile = 1;
    };
    printf("\n");
    //
    // First check if the calibration file exists:
    //
    Int_t EFILE = 0;
    printf(" Check the existence of CaloCALIBdata.root file: \n\n");
    TFile tfile(file5.str().c_str());
    if ( !tfile.IsZombie() ) {
	printf(" The file already exists! It will be updated \n\n");
	EFILE = 1;
	tfile.Close();
    } else {
	printf("\n OK, I will create it!\n\n");
	EFILE = 0;
    };
    //    EFILE = 0;
    //
    // this must be done for each file.
    //
    Long64_t neven = 0;
    TTree *trl1 = 0;
    TFile *hfl1 = 0;
    CalorimeterCalibScan *calo = new CalorimeterCalibScan();   
    if ( EFILE == 1 ){
	//
	// If the file doesn't exist create it
	//
	hfl1 = new TFile(file5.str().c_str(),"UPDATE","Calorimeter calib data");
	calo = new CalorimeterCalibScan();   
	//
	trl1 = (TTree*)hfl1->Get("CaloCALIBdata");  
	trl1->SetBranchAddress("Event", &calo);		
	neven = trl1->GetEntries()-1;
	trl1->GetEntry(neven);
	calibex = calo->evno;
	printf("neven %i calibex = %i calo->evno %i calo->rms %f \n",(int)neven,calibex,calo->evno,calo->calrms[0][0][0]);
    } else {
	//
	// If the file doesn't exist create it
	//
	hfl1 = new TFile(file5.str().c_str(),"RECREATE","Calorimeter calib data");
	//
	calo = new CalorimeterCalibScan();   
	//
	trl1 = new TTree("CaloCALIBdata","PAMELA calorimeter calibration data");
	trl1->Branch("Event","CalorimeterCalibScan",&calo);	    
    };    
    //
    const char *filename2 = Filename;
    //
    TString lfile;
    TString sfile;
    //
    Int_t e = 0;
    ifstream in;
    in.open(flist, ios::in);
    char ctime[20];
    const char *nome;
    //
    //    TString *file[17];
    TString fififile;
    const char *file;
    TString filename;
    //
    stringstream lfillo;
    //
    //
    //
    TTree *tr;
    pamela::CalibCalPedEvent *ce = 0;
    pamela::PscuHeader *cph = 0;
    pamela::EventHeader *ceh = 0;
    Long64_t ncalibs = 0;
    Int_t s = -1;
    Int_t l = 0;
    Int_t m = 0;
    Int_t ss = 0;
    //
    while ( e < nfile ){
	if ( flist != "" ){
	    in >> ctime;
	    lfillo.str("");
	    lfillo << filename2 << "/";
	    lfillo << ctime;
	    lfile = (TString)lfillo.str().c_str();
	    //file = "dw_000000_000.dat";
	    //	    file = emigetFilename(lfile);
	    fififile = getFilename(lfile);
	    file = fififile;
	    lfillo.str("");
	    lfillo << file;
	    sfile = (TString)lfillo.str().c_str();
	} else {
	    lfillo.str("");
	    lfillo << filename2;
	    lfile = (TString)lfillo.str().c_str();
	    //	    file = "dw_000000_000.dat";
	    //	    file = emigetFilename(lfile);
	    fififile = getFilename(lfile);
	    file = fififile;
	    lfillo.str("");
	    lfillo << file;
	    sfile = (TString)lfillo.str().c_str();
	};
	//
	filename = lfile;	
	nome = filename;
	printf("\n Processing file number %i: %s \n\n",e+1,nome);
	//
	const string fil = (const char *)filename;
	Int_t posiz = fil.find("dw_");
	if ( posiz == -1 ) posiz = fil.find("DW_");
	if ( posiz == -1 ) return(-1);    
	TString year;
	stringcopy(year,filename,posiz+3,posiz+5);   
	const char *ye = year;
	TString month;
	stringcopy(month,filename,posiz+5,posiz+7);   
	const char *mo = month;
	TString day;
	stringcopy(day,filename,posiz+7,posiz+9);   
	const char *da = day;
	TString fno;
	stringcopy(fno,filename,posiz+10,posiz+13);   
	const char *fn = fno;
	stringstream unino;
	//	char *unino = 0;
	//	unino = Form("%s%s%s%s",ye,mo,da,fn);
	unino.str("");
	unino << ye << mo;
	unino << da << fn;
	//
	// upgrade data...
	//    
	TFile *calheadFile = 0;
	calheadFile = getEmiFile(filename, "CalibCalPed", "Header");
	TFile *calcalibFile = 0;
	calcalibFile = getEmiFile(filename, "CalibCalPed","Event");    
	//
	const char *filen = filename;
	if ( !calheadFile || !calcalibFile ) {
	    if ( calheadFile ) calheadFile->Close();
	    if ( calcalibFile ) calcalibFile->Close();
	    printf("\n\nERROR: not able to open file: %s \n",filen);
	    goto jumpfile;
	};
	tr = (TTree*)calheadFile->Get("Pscu");
	tr->AddFriend("CalibCalPed", calcalibFile);
	tr->SetBranchAddress("Header", &ceh);
	tr->SetBranchAddress("Event", &ce);
	ncalibs    = tr->GetEntries();
	if ( ncalibs == 0 ) goto oltre;
	calo = new CalorimeterCalibScan();
	s = -1;
	l = 0;
	m = 0;	
	for (Int_t ci = 0; ci < ncalibs ; ci++){
	    tr->GetEntry(ci);	
	    //
	    // qui si deve definire "s"
	    //
	    s++;
	    if ( s == 4 ) s = 0;
	    if ( s == 0 ) ss = 0;
	    if ( s == 1 ) ss = 2;
	    if ( s == 2 ) ss = 3;
	    if ( s == 3 ) ss = 1;
	    //
	    if ( s == 0 ){
		Double_t noca = (double)ci/100.;	    
		Double_t calno = atof(unino.str().c_str())+noca;
		calo->calno = calno;
		calibex++;
		calo->evno = calibex;
	    //	    printf("unino %s atof %f calno = %f calocalno %f \n",unino,atof(unino)+noca,calno,calo->calno);
	    };
	    //
	    //
	    //
	    if (ce->cstwerr[s] != 0 && ce->cperror[s] == 0 ) {
		//		printf("ci %i , s %i \n",ci,s);
		cph = ceh->GetPscuHeader(); 				
		calo->etime[ss] = cph->GetOrbitalTime();
		for ( Int_t d=0 ; d<11 ;d++  ){
		    Int_t pre = -1;
		    if ( s == 2 ) m = 2*d+1;
		    if ( s == 3 ) m = 2*d;
		    if ( s == 0 ) m = 2*d;
		    if ( s == 1 ) m = 2*d+1;
		    if ( s == 3 ) l = 0;
		    if ( s == 2 ) l = 0;
		    if ( s == 1 ) l = 1;
		    if ( s == 0 ) l = 1;
		    for ( Int_t j=0; j<96 ;j++){
			if ( j%16 == 0 ) pre++;
			calo->calped[l][m][j] = ce->calped[ss][d][j];
			calo->cstwerr[ss] = ce->cstwerr[s];
			calo->cperror[ss] = ce->cperror[s];
			calo->calgood[l][m][j] = ce->calgood[ss][d][j];
			calo->calthr[l][m][pre] = ce->calthr[ss][d][pre];
			calo->calrms[l][m][j] = ce->calrms[ss][d][j]/4.;
			calo->calbase[l][m][pre] = ce->calbase[ss][d][pre];
			calo->calvar[l][m][pre] = ce->calvar[ss][d][pre];
		    };
		};
	    };
	    //
	    if ( s == 3 ){
		trl1->Fill();
		calo = new CalorimeterCalibScan();		
	    };
	    //
	};
	fileup++;
	//
	goto oltre;
    jumpfile: printf(" File not processed! \n ");
    oltre:
	e++;
    };
    hfl1->Write();
    hfl1->Close();
    return(0);
}
