#ifndef MARS_MAlphaFitter
#define MARS_MAlphaFitter

#ifndef MARS_MParContainer
#include "MParContainer.h"
#endif

#ifndef ROOT_TArrayD
#include <TArrayD.h>
#endif

#ifndef ROOT_TF1
#include <TF1.h>
#endif

class TH1D;

class MAlphaFitter : public MParContainer
{
private:
    TF1 *fFunc;

    Float_t fSigInt;
    Float_t fSigMax;
    Float_t fBgMin;
    Float_t fBgMax;
    Int_t   fPolynomOrder;

    Double_t fSignificance;
    Double_t fEventsExcess;
    Double_t fEventsSignal;
    Double_t fEventsBackground;

    Double_t fChiSqSignal;
    Double_t fChiSqBg;
    Double_t fIntegralMax;

    TArrayD fCoefficients;

public:
    // Implementing the function yourself is only about 5% faster
    MAlphaFitter() : fFunc(new TF1("", "gaus(0) + pol1(3)", 0, 90)), fSigInt(10), fSigMax(75), fBgMin(45), fBgMax(85), fPolynomOrder(1), fCoefficients(3+fPolynomOrder+1)
    {
        gROOT->GetListOfFunctions()->Remove(fFunc);
    }

    MAlphaFitter(const MAlphaFitter &f) : fFunc(0)
    {
        f.Copy(*this);
    }
    ~MAlphaFitter()
    {
        delete fFunc;
    }

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

        f.fSigInt       = fSigInt;
        f.fSigMax       = fSigMax;
        f.fBgMin        = fBgMin;
        f.fBgMax        = fBgMax;
        f.fPolynomOrder = fPolynomOrder;
        f.fCoefficients.Set(fCoefficients.GetSize());
        f.fCoefficients.Reset();

        TF1 *fcn = f.fFunc;
        f.fFunc = new TF1(*fFunc);
        gROOT->GetListOfFunctions()->Remove(f.fFunc);
        delete fcn;
    }

    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 SetPolynomOrder(Int_t s)          { fPolynomOrder = s; delete fFunc; fFunc=new TF1 ("", Form("gaus(0) + pol%d(3)", s));
        gROOT->GetListOfFunctions()->Remove(fFunc);
        fCoefficients.Set(3+s+1); fCoefficients.Reset(); }

    Double_t GetEventsExcess() const       { return fEventsExcess; }
    Double_t GetEventsSignal() const       { return fEventsSignal; }
    Double_t GetEventsBackground() const   { return fEventsBackground; }

    Double_t GetSignificance() const       { return fSignificance; }
    Double_t GetChiSqSignal() const        { return fChiSqSignal; }
    Double_t GetChiSqBg() const            { return fChiSqBg; }

    Double_t GetGausSigma() const          { return fCoefficients[2]; }
    Double_t GetGausMu() const             { return fCoefficients[1]; }
    Double_t GetGausA() const              { return fCoefficients[0]; }
    Double_t GetCoefficient(Int_t i) const { return fCoefficients[i]; }
    const TArrayD &GetCoefficients() const { return fCoefficients; }

    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)
};

#endif
