#ifndef MARS_MHAlpha
#define MARS_MHAlpha

#ifndef MARS_MH
#include "MH.h"
#endif

#ifndef MARS_MTime
#include "MTime.h"
#endif

#ifndef ROOT_TH3
#include <TH3.h>
#endif

class MParList;
class MParameterD;
class MEnergyEst;
class MHMatrix;
class MPointingPos;


class MAlphaFitter : public MParContainer
{
private:
    Float_t fSigInt;
    Float_t fSigMax;
    Float_t fBgMin;
    Float_t fBgMax;
    Int_t   fPolynom;

    Double_t fSignificance;
    Double_t fExcessEvents;
    Double_t fChiSqSignal;
    Double_t fChiSqBg;
    Double_t fSigmaGaus;
    Double_t fIntegralMax;

public:
    MAlphaFitter() : fSigInt(10), fSigMax(75), fBgMin(45), fBgMax(85), fPolynom(2)
    {
    }

    MAlphaFitter(const MAlphaFitter &f)
    {
        f.Copy(*this);
    }

    void Copy(TObject &o) const
    {
        MAlphaFitter &f = static_cast<MAlphaFitter&>(o);

        f.fSigInt  = fSigInt;
        f.fSigMax  = fSigMax;
        f.fBgMin   = fBgMin;
        f.fBgMax   = fBgMax;
        f.fPolynom = fPolynom;
    }

    void SetSignalIntegralMax(Float_t s) { fSigInt = s; }
    void SetSignalFitMax(Float_t s)      { fSigMax = s; }
    void SetBackgroundFitMin(Float_t s)  { fBgMin = s; }
    void SetBackgroundFitMax(Float_t s)  { fBgMax = s; }
    void SetNumPolynom(Int_t s)          { fPolynom = s; }

    Double_t GetExcessEvents() const { return fExcessEvents; }
    Double_t GetSignificance() const { return fSignificance; }
    Double_t GetChiSqSignal() const  { return fChiSqSignal; }
    Double_t GetChiSqBg() const      { return fChiSqBg; }
    Double_t GetSigmaGaus() const    { return fSigmaGaus; }

    void PaintResult(Float_t x=0.04, Float_t y=0.94, Float_t size=0.035) const;

    Bool_t Fit(TH1D &h, Bool_t paint=kFALSE);
    ClassDef(MAlphaFitter, 1)
};


class MHAlpha : public MH
{
private:
    MAlphaFitter fFit;

    TH3D fHAlpha;               // Alpha vs. theta and energy
    TH1D fHEnergy;              // excess events vs energy
    TH1D fHTheta;               // excess events vs theta
    TH1D fHTime;                // excess events vs time;
    TH1D fHAlphaTime;           //! temporary histogram to get alpha vs. time

    MParameterD  *fResult;      //!
    MEnergyEst   *fEnergy;      //!
    MPointingPos *fPointPos;    //!

    MTime   *fTimeEffOn;        //! Time to steer filling of fHTime
    MTime   *fTime;             //! Event-Time to finalize fHTime
    MTime    fLastTime;         //! Last fTimeEffOn

    const TString fNameProjAlpha;  //! This should make sure, that gROOT doen't confuse the projection with something else

    MHMatrix *fMatrix;          //!
    Int_t fMap[2];              //!

    void FitEnergySpec(Bool_t paint=kFALSE);
    void FitEnergyBins(Bool_t paint=kFALSE);
    void FitThetaBins(Bool_t paint=kFALSE);

    void UpdateAlphaTime(Bool_t final=kFALSE);
    void InitAlphaTime(const MTime &t);
    void FinalAlphaTime(MBinning &bins);

    void PaintText(Double_t val, Double_t error) const;

public:
    MHAlpha(const char *name=NULL, const char *title=NULL);

    Bool_t SetupFill(const MParList *pl);
    Bool_t Fill(const MParContainer *par, const Stat_t w=1);
    Bool_t Finalize();

    const TH3D &GetHist() const { return fHAlpha; }
    const MAlphaFitter &GetAlphaFitter() const { return fFit; }

    void Paint(Option_t *opt="");
    void Draw(Option_t *option="");

    void InitMapping(MHMatrix *mat);
    void StopMapping();

    ClassDef(MHAlpha, 1) // Alpha-Plot which is fitted online
};

#endif
