/**
 * \file CaloProfile.h
 * \author Emiliano Mocchiutti
 */
#ifndef caloprofile_h
#define caloprofile_h

#define EMPTY -1
#define MAX 50

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <TTree.h>
#include <TFriendElement.h>
#include <TChain.h>
#include <TCanvas.h>
#include <TGraph.h>
#include <TH1F.h>
#include <TH2F.h>
#include <TFile.h>
#include <TPolyLine.h>
#include <TMath.h>
#include <TStyle.h>
#include <TList.h>
#include <TKey.h>
#include <TSystemFile.h>
#include <TSystemDirectory.h>
#include <TSQLServer.h>
#include <TF1.h>
#include <TGraphErrors.h>
#include <TMinuit.h>

#include <PamLevel2.h>

using namespace std;

struct stack{
    char data[MAX];
    int top;
};

/**
 *
 */
class CaloLat : public TObject {

 private:
    //
    PamLevel2 *L2;
    Bool_t debug;
    //
    // needed to avoid reprocessing the same event over and over to obtain the variables
    //
    UInt_t OBT;
    UInt_t PKT;
    UInt_t atime;
    //
    Float_t estrip[2][22][96];
    TString suf;
    Bool_t usepl18x;
    //

 public:
    //
    //
    void Draw();
    void Draw(Int_t,Int_t);
    //
    CaloLat();
    CaloLat(PamLevel2 *L2);
    ~CaloLat(){ Delete(); };
    //
    void SetDebug(Bool_t d){ debug=d; };
    //
    void Clear();
    void Clear(Option_t *option){Clear();};
    void Delete();
    void Delete(Option_t *option){Delete();};
    //
    void Process(); ///< Process data 
    void Print();
    void Print(Option_t *option){Print();};
    //
    
    void UsePlane18X(Bool_t use){usepl18x = use;};
    //
    //
    void SetSuffix(TString suffix){ suf = suffix;};
    //
    ClassDef(CaloLat,3);
};

/**
 *
 */
class CaloLong : public TObject {

 private:
    //
    PamLevel2 *L2;
    Bool_t debug;
    //
    // needed to avoid reprocessing the same event over and over to obtain the variables
    //
    UInt_t OBT;
    UInt_t PKT;
    UInt_t atime;
    UInt_t fOBT;
    UInt_t fPKT;
    UInt_t fatime;
    //
    Int_t N;
    Int_t NC;
    Bool_t sel;
    Bool_t cont;
    Int_t mask18b;
    Bool_t usepl18x;
    //
    Float_t chi2;
    Float_t ndf;
    Float_t E0;
    Float_t a;
    Float_t b;
    Float_t errE0;
    Float_t erra;
    Float_t errb;
    Float_t etmax;
    Float_t asymm;
    Float_t X0pl;
    Float_t defE0;
    Float_t umax;
    Float_t lmax;
    TString sumax;
    TString slmax;
    Int_t fitresult;
    //
    Bool_t no18x;
    Bool_t maskXE;
    Bool_t maskYE;
    Bool_t maskXO;
    Bool_t maskYO;
    //
    Bool_t xyaverage;
    //
    Bool_t heavytail;
    Float_t letmax;
    Float_t lmipth;
    //
    Float_t eplane[2][22];
    //
    CaloLevel2 *clp;
    //
    Float_t Evaluate(TString s, Float_t tmax, Float_t X0pl ); // expression must be of the form "tmax+2.*X0pl", "5*tmax"."tmax+10","tmax-(4*tmax)+3.*X0pl"...
    //
    TString suf;
    TF1 *lfit;

 public:
    //
    //
    void Fit();
    void Fit(Bool_t draw);
    TF1 *GetFit();
    //
    //    Double_t ccurve(Double_t *t, Double_t *par); 
    //
    void SetCaloLevel2Pointer(CaloLevel2 *cp){ clp = cp;};
    //
    Float_t Get_E0(){this->Fit(); return E0;};
    Float_t Get_defE0(){this->Fit(); return defE0;};
    Float_t Get_a(){this->Fit(); return a;};
    Float_t Get_b(){this->Fit(); return b;};
    Float_t Get_errE0(){this->Fit(); return errE0;};
    Float_t Get_erra(){this->Fit(); return erra;};
    Float_t Get_errb(){this->Fit(); return errb;};
    Float_t Get_chi2(){this->Fit(); return chi2;};
    Float_t Get_ndf(){this->Fit(); return ndf;};
    Float_t Get_nchi2(){this->Fit(); if ( ndf > 0 ) return (chi2/ndf); return 0;};
    Float_t Get_tmax(){this->Fit(); if ( b != 0 ) return ((a-1.)/b); return 0;};
    Float_t Get_asymm(){this->Fit(); return asymm;};
    Float_t Get_exptmax(){this->Process(); return etmax;};
    Float_t Get_X0pl(){this->Process(); return X0pl;};
    //
    Float_t Get_letmax(){ return letmax;};
    Float_t Get_lmipth(){ return lmipth;};
    Int_t Get_fitresult(){this->Fit(); return fitresult;};    
    //
    void ForceNextFit(){atime=0;fatime=0;};
    void Draw();
    void Draw(Int_t);
    //
    CaloLong();
    CaloLong(PamLevel2 *L2);
    ~CaloLong(){ Delete(); };
    //
    void SetDebug(Bool_t d){ debug=d; };
    //    void UsePlane18X(){ no18x=false; };
    
    void UsePlane18X(Bool_t use="false"){usepl18x = use; no18x=!use;};
    //
    //
    void UseAverage(){ xyaverage = true;};
    void UseAllMeas(){ xyaverage = false;};
    //
    void MaskSection(TString);
    void UnMaskSection(TString);
    void UnMaskSections();
    void Selection(){sel = true; cont = false;}; ///< Set selection mode: planes from 1 to 22-N are used, plane 18 - N is masked if "emulate18" variable is true (DEFAULT);
    void Contamination(){sel = false; cont = true;}; ///< Set contamination mode: planes from N to 22 are used.
    void SetNoWpreSampler(Int_t n);
    void SetNoWcalo(Int_t n);
    void SplitInto(Int_t NoWpreSampler, Int_t NoWcalo);
    Int_t GetNoWpreSampler(){return N;}; ///< Get the number of W planes used as presampler. 
    Int_t GetNoWcalo(){return NC;}; ///< Get the number of W planes used as calorimeter.
    void SetEnergies(Float_t myene[][22]);
    //
    void SetLowerLimit(Float_t l){ lmax = l; };
    void SetUpperLimit(Float_t u){ umax = u; };
    void SetLowerLimit(TString sl){ slmax = sl; };// expression must be of the form "5*t"."t+10","t-(4*t)"... where t will be replaced by the fitted maximum (X0)
    void SetUpperLimit(TString su){ sumax = su; };// expression must be of the form "5*t"."t+10","t-(4*t)"... where t will be replaced by the fitted maximum (X0)
    //
    void Setletmax(Float_t l){ letmax = l;};
    void Setlmipth(Float_t l){ lmipth = l;};
    void HeavyTail(Bool_t b){ heavytail=b;};
    //
    Float_t GetLowerLimit(){ return lmax;};
    Float_t GetUpperLimit(){ return umax;};
    //
    void SetSuffix(TString suffix){ suf = suffix;};
    //
    void Clear();
    void Clear(Option_t *option){Clear();};
    void Delete();
    void Delete(Option_t *option){Delete();};
    //
    void Process(); ///< Process data 
    void Print();
    void Print(Option_t *option){Print();};
    //
    ClassDef(CaloLong,4);
};

/**
 *
 */
class Calo2D : public TObject {

 private:
    //
    PamLevel2 *L2;
    Bool_t debug;
    //
    // needed to avoid reprocessing the same event over and over to obtain the variables
    //
    UInt_t OBT;
    UInt_t PKT;
    UInt_t atime;
    //
    Float_t estrip[23][96][96];
    Int_t smax[23];
    Int_t smay[23];
    Bool_t usepl18x;
    //
    TString suf;

 public:
    //
    //
    void Draw();
    void Draw(Int_t);
    //
    Calo2D();
    Calo2D(PamLevel2 *L2);
    ~Calo2D(){ Delete(); };
    //
    void SetDebug(Bool_t d){ debug=d; };
    //
    void Clear();
    void Clear(Option_t *option){Clear();};
    void Delete();
    void Delete(Option_t *option){Delete();};
    //
    void SetSuffix(TString suffix){ suf = suffix;};
    
    void UsePlane18X(Bool_t use){usepl18x = use;};
    //
    //
    void Process(); ///< Process data 
    void Print();
    void Print(Option_t *option){Print();};
    //
    ClassDef(Calo2D,3);
};

#endif

