#ifndef MARS_MExtralgoSpline
#define MARS_MExtralgoSpline

#ifndef ROOT_TROOT
#include <TROOT.h>
#endif

class MExtralgoSpline
{
public:  
    enum ExtractionType_t { kAmplitude, kIntegral };    //! Possible time and charge extraction types

private:
    ExtractionType_t fExtractionType;

private:
    //Bool_t fIsOwner; // Owner of derivatives....

    // Input
    Float_t *fVal;
    Int_t    fNum;

    Float_t *fDer1;
    Float_t *fDer2;

    Float_t fRiseTime;
    Float_t fFallTime;

    Float_t fResolution;

    // Result
    Float_t fTime;
    Float_t fTimeDev;
    Float_t fSignal;
    Float_t fSignalDev;

    inline Float_t Eval(Float_t val, Float_t a, Float_t deriv) const
    {
        return a*val + (a*a*a-a)*deriv;
    }

    inline Float_t Eval(const Float_t x, const Int_t i) const
    {
        const Float_t b = x-i;
        return Eval(fVal[i], 1-b, fDer2[i]) + Eval(fVal[i+1], b, fDer2[i+1]);
    }

    void InitDerivatives() const;
    Float_t CalcIntegral(Float_t start, Float_t range) const;

public:
    MExtralgoSpline(Float_t *val, Int_t n, Float_t *der1, Float_t *der2)
        : fExtractionType(kIntegral), fVal(val), fNum(n), fDer1(der1), fDer2(der2), fTime(0), fTimeDev(-1), fSignal(0), fSignalDev(-1)
    {
        InitDerivatives();
    }

    void SetRiseFallTime(Float_t rise, Float_t fall) { fRiseTime=rise; fFallTime=fall; }
    void SetExtrationType(ExtractionType_t typ)      { fExtractionType = typ; }
    void SetResolution(Float_t res)                  { fResolution=res; }

    Float_t GetTime() const      { return fTime; }
    Float_t GetSignal() const    { return fSignal; }

    Float_t GetTimeDev() const   { return fTimeDev; }
    Float_t GetSignalDev() const { return fSignalDev; }

    void GetSignal(Float_t &sig, Float_t &dsig) const { sig=fSignal; dsig=fSignalDev; }
    void GetTime(Float_t &sig, Float_t &dsig) const   { sig=fTime; dsig=fTimeDev; }

    Float_t ExtractNoise(Int_t iter);
    void Extract(Byte_t sat, Int_t maxpos);
};

#endif
