/**
 * \file inc/CaloLevel0.h
 * \author Emiliano Mocchiutti
**/
#ifndef CaloLevel0_h
#define CaloLevel0_h
#include <TObject.h>
#include <TROOT.h>
//
// YODA headers
//
#include <PamelaRun.h>
#include <physics/calorimeter/CalorimeterEvent.h>
#include <CalibCalPedEvent.h>
//
#include <CaloCore.h>
#include <CaloLevel1.h>
#include <CaloLevel2.h>

using namespace pamela::calorimeter;

/**
 * \brief Class needed to calibrate calorimeter data.
 *
 * Calibrates data and connects to fortran routines using structures.
 *
**/
class CaloLevel0 : public TObject {

 private:

 public:
    Bool_t debug; ///< debugging flag
    Bool_t verbose; ///< verbose flag
    Bool_t crosst;
    //
    // variables in which it is stored the calibration information for the four sections
    //
    UInt_t idcalib[4]; ///< ID of root file containing calibrations (one per section)
    UInt_t fromtime[4]; ///< lower validity time limit
    UInt_t totime[4]; ///< upper validity time limit
    Int_t calibno[4]; ///< entry of the file
    TString fcalname[4]; ///< filename of calibrations
    //
    // variables needed to open level0 files
    //
    TTree *l0tr; ///< level0 tree
    TBranch *l0calo; ///< level0 calorimeter branch
    pamela::calorimeter::CalorimeterEvent *de; ///< level0 calorimeter object

    void Set(){ de = new CalorimeterEvent(); };    

    void Clear(){};
    void* GetPointerToCalorimeterEvent(){ return &de; };
    CalorimeterEvent* GetCalorimeterEvent(){ return de; };
    //
    //
    // variables from the calorimeter online calibration
    //
    Float_t calped[2][22][96]; ///< pedestals
    Float_t calgood[2][22][96]; ///< used or not in the common noise calculation
    Float_t calthr[2][22][6]; ///< thresholds
    Float_t calrms[2][22][96]; ///< rms
    Float_t calbase[2][22][6]; ///< baselines (common noise) during calibration
    Float_t calvar[2][22][6]; ///< variance
    Float_t cstwerr[4]; ///< status word
    Float_t cperror[4]; ///< unpacking error flag
    //
    // variables needed to calibrate the calorimeter event by event basis
    //
    Float_t dexy[2][22][96]; ///< compressed ADC data
    Float_t dexyc[2][22][96]; ///< RAW ADC data
    Float_t base[2][22][6]; ///< baselines for this event
    Float_t sbase[2][22][6]; ///< saved baselines from previous events
    //
    // Energy vector
    //
    Int_t istrip; ///< number of strip above threshold
    Int_t svstrip[4224]; ///< saved calibrated energy
    //
    // Variables needed to handle parameters files
    //
    Bool_t calopar1; ///< boolean, is true if parameter set number 101 has already been loaded
    Bool_t calopar2; ///< boolean, is true if parameter set number 102 has already been loaded
    Bool_t calopar3; ///< boolean, is true if parameter set number 103 has already been loaded
    UInt_t ftcalopar1; ///< parameter set 101 lower limit validity
    UInt_t ttcalopar1; ///< parameter set 101 upper limit validity
    UInt_t ftcalopar2; ///< parameter set 102 lower limit validity
    UInt_t ttcalopar2; ///< parameter set 102 upper limit validity
    UInt_t ftcalopar3; ///< parameter set 103 lower limit validity
    UInt_t ttcalopar3; ///< parameter set 103 upper limit validity
    //
    // private methods
    //
/**
 * \param s calorimeter section.
**/
    void ClearCalibVals(Int_t s); ///< clear calibration values for section s
    void ClearCommonVar(); ///< clear common variables
    void ClearTrkVar();  ///< clear track-related variables
    void FindBaseRaw(Int_t l, Int_t m, Int_t pre); ///< calculate baselines starting from RAW data
    Int_t Update(TSQLServer *dbc, UInt_t atime, Int_t s); ///< update calibration for this event
    Int_t LoadCalib(Int_t s); ///< load calibrations

    //
    // ADC to MIP conversion values
    //
    Float_t mip[2][22][96]; ///< ADC to MIP conversion values
    Int_t obadmask[2][22][96]; ///< Offline mask of bad strips (not used to calculate baselines and calorimeter variables)	
    Float_t emin; ///< Offline threshold to separate noise from signal
    //
    // Structures to pass data from/to F77
    //
    struct FlCaLevel1 *clevel1; ///< input structure
    struct FlCaLevel2 *clevel2; ///< output structure
    //
    //
    //
    Int_t trkseqno; ///< tracker track sequential number (-1 if calorimeter selftrigger)
    //
    // useful methods
    //
    Int_t ChkParam(TSQLServer *dbc, UInt_t runheader, Bool_t mech); ///< check and load parameters data
    Int_t ChkCalib(TSQLServer *dbc, UInt_t atime); ///< check and load calibration data
    Int_t Calibrate(Int_t ei); ///< perform data calibration
    void GetCommonVar(); ///< call fortran common variables program
    void GetTrkVar(); ///< call fortran track-related variables program
    void ClearStructs(); ///< clear input and output structures 
    void FillCommonVar(CaloLevel1 *c1, CaloLevel2 *ca); ///< copy common variables from structure to class
    void FillTrkVar(CaloLevel2 *ca, Int_t nutrk); ///< copy track-related variables from structure to class
    void RunClose(); ///< clear variables which could change from one run to another
    void SetCrossTalk(Bool_t ct);
    void SetVerbose(Bool_t ct);
    //
    // constructor
    //
    CaloLevel0(); ///< contructor
    void ProcessingInit(TSQLServer *dbc, UInt_t hs, Int_t &sgnl, TTree *l0tree, Bool_t debug, Bool_t verbose); ///< initialize caloprocessing object
    //
    // destructor
    //
    ~CaloLevel0();///< destructor
    //
    ClassDef(CaloLevel0,1);
};

#endif
