#ifndef MARS_MExtractTimeAndChargeSpline
#define MARS_MExtractTimeAndChargeSpline

#ifndef MARS_MExtractTimeAndCharge
#include "MExtractTimeAndCharge.h"
#endif

#ifndef MARS_MArrayF
#include "MArrayF.h"
#endif

class MPedestalPix;
class MExtractTimeAndChargeSpline : public MExtractTimeAndCharge
{

private:
  
  static const Byte_t  fgHiGainFirst;    //! Default for fHiGainFirst  (now set to: 2)
  static const Byte_t  fgHiGainLast;     //! Default for fHiGainLast   (now set to: 14)
  static const Byte_t  fgLoGainFirst;    //! Default for fLoGainFirst  (now set to: 2)
  static const Byte_t  fgLoGainLast;     //! Default for fLoGainLast   (now set to: 14)
  static const Float_t fgResolution;     //! Default for fResolution   (now set to: 0.003)
  static const Float_t fgRiseTime;       //! Default for fRiseTime     (now set to: 1.5)
  static const Float_t fgFallTime;       //! Default for fFallTime     (now set to: 4.5)

  MArrayF fHiGainSignal;                //! Need fast access to the signals in a float way
  MArrayF fLoGainSignal;                //! Store them in separate arrays
  MArrayF fHiGainFirstDeriv;            //! High-gain discretized first derivatives
  MArrayF fLoGainFirstDeriv;            //! Low-gain discretized first derivatives
  MArrayF fHiGainSecondDeriv;           //! High-gain discretized second derivatives
  MArrayF fLoGainSecondDeriv;           //! Low-gain discretized second derivatives

  Float_t fAbMax;                        //! Current maximum of the spline
  Float_t fAbMaxPos;                     //! Current position of the maximum of the spline
  Float_t fHalfMax;                      //! Current half maximum of the spline

  Float_t fResolution;                   // The time resolution in FADC units
  Float_t fRiseTime;                     // The usual rise time of the pulse
  Float_t fFallTime;                     // The usual fall time of the pulse

  Int_t   fRandomIter;                   // Counter used to randomize weights for noise calculation
  
  Byte_t  fFlags;                        // Bit-field to hold the time extraction types
  
  Int_t  ReadEnv(const TEnv &env, TString prefix, Bool_t print);

  Bool_t InitArrays();
  
  void CalcIntegralHiGain(Float_t &sum, Float_t start, Float_t last);
  void CalcIntegralLoGain(Float_t &sum, Float_t start, Float_t last);

public:

  enum ExtractionType_t { kMaximum,   kHalfMaximum,
                          kAmplitude, kIntegral    };    //! Possible time and charge extraction types

private:

  Bool_t IsExtractionType ( ExtractionType_t typ )  { return TESTBIT(fFlags, typ); }
  
public:

  MExtractTimeAndChargeSpline(const char *name=NULL, const char *title=NULL);
  ~MExtractTimeAndChargeSpline() {}

  Float_t GetRiseTime() const { return fRiseTime; }
  Float_t GetFallTime() const { return fFallTime; }

  void SetRange      ( Byte_t hifirst=0, Byte_t hilast=0, Byte_t lofirst=0, Byte_t lolast=0 );  
  void SetResolution ( const Float_t f=fgResolution  )  { fResolution  = f;  }
  void SetRiseTime   ( const Float_t f=fgRiseTime    )  { fRiseTime    = f;  }
  void SetFallTime   ( const Float_t f=fgFallTime    )  { fFallTime    = f;  }

  void SetTimeType   ( const ExtractionType_t typ=kHalfMaximum ); 
  void SetChargeType ( const ExtractionType_t typ=kAmplitude);
  
  void FindTimeAndChargeHiGain(Byte_t *first, Byte_t *logain, Float_t &sum, Float_t &dsum,
                               Float_t &time, Float_t &dtime,
                               Byte_t &sat, const MPedestalPix &ped, const Bool_t abflag);
  void FindTimeAndChargeLoGain(Byte_t *first, Float_t &sum,  Float_t &dsum,
                               Float_t &time, Float_t &dtime,
                               Byte_t &sat, const MPedestalPix &ped, const Bool_t abflag);

  ClassDef(MExtractTimeAndChargeSpline, 1)   // Task to Extract Arrival Times and Charges using a Fast Cubic Spline
};

#endif



