#ifndef caloelectron_h
#define caloelectron_h


#if !defined(__CINT__) || defined(__MAKECINT__)

#include <PamLevel2.h>

//#include <TMinuit.h>
#include <TPaveStats.h>
#include <TStyle.h>
#include <TSystem.h>
#include <TCanvas.h>
#include <TGraphErrors.h>
#include <TH1F.h>
#include <TF2.h>
#include <TH2F.h>
#include <TProfile.h>
#include <TBenchmark.h>

#include <iostream>
#include <iomanip>
using namespace std;

#endif

//CaloLevel1* cl1;

#define NTAUBINMAX 100

#define WX0 0.350 //cm
#define WTICK 0.26 //cm
#define PITCH 0.244 //cm
#define DEAD 0.096 //cm
#define GLUE 0.05  //cm

#define CALIBNBIN 600
#define CALIBRANGE 15.//cm

double fradpro(Double_t *xi, Double_t *parmin);

///////////////////////////////////////////////////
///
///
///  CLASS FOR INITIALIZATIONS & PARAMETERS
///
///
///////////////////////////////////////////////////

class CaloElectron_parameters : public TObject{

 private:
    
    CaloElectron_parameters(){ SetDefault(); };
    
    static CaloElectron_parameters * _parameters;

 public:

    static CaloElectron_parameters *Get(){
	if(_parameters==0) {
//	    cout << "**NEW**"<<endl;
	    _parameters = new CaloElectron_parameters();
	}
	return _parameters;
    }
    
    // ------
    //general
    // ------

    bool debug;	

    int isimu;	   //simulation flag
    int dolongfit; //longitudinal-fit flag
    int dolatcorr; //lateral-correction flag
    int calibmode; //calibration flag

    float TAUMAX;  // max longitudinal depth to evaluate qtot (TAU=t/T)
    float RMAX;    // max radius around the track to evaluate qtot

    float RMAXsp;  // radius around the track to integrate the profile

    int ipmin; // first plane (0-21)
    int ipmax; // last plane (0-21)

    bool maskpl[22][2];  // plane masks

    CaloLevel1* cl1;

    // -----------------------
    // plots of energy deposit
    // -----------------------   
    TH2F *h_qtot[2]; //matrix of energy deposits (measured) 192x22
    TH2F *h_qfit[2]; //matrix of energy deposits (fit) 192x22

    // --------------------------------------
    // parameters for lateral profile (fixed)
    // --------------------------------------
    
    float file_rt[12][3];
    float file_rc[12][3];
    float file_p[12][3];
    float file_tau[12];

    void Dump();

    void SetCalo(int icalo,int notused);
    void SetPar();
    void SetPar(TString pathx,TString pathyd,TString pathyp);
    void SetRMAX(float setRMAX)    {RMAX   = setRMAX;};
    void SetRMAXsp(float setRMAX)  {RMAXsp = setRMAX;};
    void SetTAUMAX(float setTAUMAX){TAUMAX = setTAUMAX;};
    void Setsimu(int isetsimu)     {isimu=isetsimu; SetPar();};
    void SetLongitudinalFit(int isetdolongfit) {dolongfit = isetdolongfit;};
    void SetLateralCorrection(int isetdolatcorr) {dolatcorr = isetdolatcorr;};
    void SetCalibrationMode(int icalibmode){calibmode=icalibmode;};
    void SetDebug(bool isetdebug)        {debug = isetdebug;};
    //
    void SetCaloLevel1(CaloLevel1 *cl1in)  {cl1 = cl1in; };

    void SetDefault();
    

    // --------------------------------------
    // tools for calibration (NTAUBINMAX)
    // --------------------------------------
    //
    TH2F *h_qtot_tau[100][3];///< profile histos for x,yodd,yeven
    TH1F *h_qtot_tau_wav[100][3];///< profile histos for x,yodd,yeven (weighted average)
    double summW[100][3][1000];
    double summWF[100][3][1000];
    //
    float par_rt[100][3];
    float par_rc[100][3];
    float par_p[100][3];
    int   par_ntau;
    float par_taubin[101];
    //
    void Calibration_SetTools();
    void Calibration_SetTools(int ntau, float* taubin);
    void Calibration_Fit();
    void Calibration_Save(TFile* file);
    void Calibration_Load(TFile* file);

    ClassDef(CaloElectron_parameters,2);

};

///////////////////////////////////////////////////
///
///
///  CLASS INPLEMENTATION
///
///
///////////////////////////////////////////////////
class CaloElectron : public TObject{

 private:
    
 public:

    
    // -----------
    // shower axis
    // -----------
    float trkcoordx[22][2]; ///< track coordinates (PAMELA r.s.)
    float trkcoordy[22][2]; ///< track coordinates (PAMELA r.s.)
    float trkstrip[22][2]; ///< strip traversed by the track
    float tgx,tgy,tg;	    
    // --------------
    // energy deposit
    // --------------
    float qtot;            ///< total collected charge 
    float qplane0[22][2];  ///< collected charge (within RMAX & TAUMAX)
    float qplane1[22][2];  ///< corrected charge (lateral leakage & gaps) 
    float qplanefit[22][2];  ///< fitted values 
    float tplane[22][2];   ///< shower depth (in units of radiation lenth) 
    // --------------------------------
    // parameters from longitudinal fit
    // --------------------------------
    float chi2__l;    // output longitudinal fit (chi2)
    float par__l[4];  // parameters (E,alpha,T,t0)
    int   err__l; // minuit flag (0=ok ecc...)
    float corr__l;      // longitudinal correction factor

    float chi2;      ///< global chi2 (lateral+longitudinal)     

    // --------------
    // new variables
    // --------------
    float RMS[22][2];
    float SKEW[22][2];
    float KURT[22][2];
    float TAU[22][2];
    
 
    CaloElectron(){ Reset(); };
    CaloElectron(PamLevel2 *l2, int ntr){ Reset(); Set(l2,ntr); }; 

/*     CaloElectron(){ Reset(); SetDefault(); SetPar(); }; */
/*     CaloElectron(PamLevel2 *l2, int ntr){ Reset(); SetPar(); Set(l2,ntr); SetDefault();}; */
/*     CaloElectron(PamLevel2 *l2){ Reset(); SetPar(); Set(l2); SetDefault();}; */

    ~CaloElectron(){ Reset(); };
    
    void Reset();
    void Clear(){ Reset(); };
    void Delete(){ Reset(); };

    bool Set(CaloLevel1*,float tracoo[][2]);//main set
    bool Set(CaloLevel1*,CaloTrkVar*);
    bool Set(PamLevel2*,int);

//    bool Set(PamLevel2* l2){ return Set(l2,0); };
//    bool Set(CaloLevel1*,float tracoo[][2]);
//    bool Set(CaloLevel1*,CaloLevel2*);

    // -------------------------------------
    // methods to perform lateral correction
    // -------------------------------------
    double GetLateralCorrection(double,double,int,int);
    double GetLateralCorrection(double,double,TF2*,int);
    float  ApplyLateralCorrection(float);
    void   GetProfile(int,int,float xx[],float qq[],float errxx[],float errqq[]);    
//    float GetLateralFactor(){return corr;};
    TGraphErrors* GetGraph_Lateral(int, int);  
    TGraphErrors* GetFunc_Lateral(int,int);  
    // ------------------------------------------
    // methods to perform longitudinal correction
    // ------------------------------------------
    int   ApplyLongitudinalFit(int longto);//return the ierflg value of gminuit minimization
    float GetLongitudinalCorrection();
//    float GetLongitudinalFactor(){return corr__l;};
//    float GetLongitudinalFcnout(){return chi2__l;};
    float GetIerflg(){return err__l;};
    TGraphErrors* GetGraph_Longitudinal();  
    TGraphErrors* GetGraph_Longitudinal_Fit();  
    TGraphErrors* GetGraph_Longitudinal_Integral();  
    TGraphErrors* GetGraph_Longitudinal_Integral_Fit();  
    TF1*          GetFunc_Longitudinal(); 
    float         GetMaxResidual();
    int           GetNRun();
    float         GetMaxRun();
    // ------------------------------------
    // other methods
    // ------------------------------------
    float ProfileTest();
    void  GetCornerCoord(int,int,float&,float&);
    void  Print();
    int   GetNWLayers(int ip,int iv){ return ip+(1-iv);}; ///< n.W-layers above an active layer
    // ------------------------------------
    // methods to get some shower variables
    // ------------------------------------
    float GetQ(int icorr);           ///< shower charge (within RMAX and TAUMAX)
    float GetQ(){ return GetQ(1); }; ///< shower charge (within RMAX and TAUMAX)
    float GetQView(int icorr,int iv);///< shower charge on x or y view
/*     float GetQW(int icorr,int iw);            */
/*     float GetQW(int icorr,int iw,int iv);    */
/*     float GetQipiv(int icorr,int ip,int iv);       */
    float GetEnergy(int icorr);      ///< shower energy
    float GetEnergy(){ return GetEnergy(1); };///< shower energy
    float GetShowerMaximum(float qplane[][2]); 
    float GetShowerMaximum(int icorr);///< shower maximum (in units of W-layers)
    float GetShowerMaximumX0(int icorr);///< shower maximum (in units of X0)
    float GetShowerMaximumView(int view,float qplane[][2]);
    float GetShowerMaximumView(int view,int icorr);///< shower maximum (in units of W-layers)
    float GetShowerMaximumViewX0(int view,int icorr);///< shower maximum (in units of X0)
/*     float GetStripMaximum(int iv,int icorr);///< strip traversed by track on maximum plane */
/*     float GetCoordMaximum(int iv,int icorr);///< coordinate traversed by track on maximum plane */
/*     float GetStripW(int iw,int iv);///< coordinate traversed by track after iw tungsten planes */
/*     float GetCoordW(int iw,int iv,int ixy);///< coordinate traversed by track after iw tungsten planes */
/*     float GetmaxStrip(int ip,int iv); */


    bool IsInsideFiducial(int level); 

    // ------------------------------------
    // methods to perform calibration
    // ------------------------------------
    void Calibration_Fill();
    

    ClassDef(CaloElectron,4);

};



#endif
