#ifndef MARS_MExtractor
#define MARS_MExtractor

/////////////////////////////////////////////////////////////////////////////
//                                                                         //
// MExtractor                                                              //
//                                                                         //
// Base class for the signal extractors                                    //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////

#ifndef MARS_MTask
#include "MTask.h"
#endif

class MRawEvtData;
class MRawRunHeader;

class MPedestalCam;
class MExtractedSignalCam;

class MExtractor : public MTask
{
private:

  static const Float_t fgOffsetLoGain;     //! Default for fOffsetLoGain (now set to 1.51 (= 5ns)
  
protected:

  static const Byte_t  fgSaturationLimit;  //! Default for fSaturationLimit (now set to: 254)
  static const TString fgNamePedestalCam;  //! "MPedestalCam"

  Float_t fOffsetLoGain;                  // Offset of the low-gain signal w.r.t. the High-Gain slices

  MPedestalCam        *fPedestals;         //! Pedestals of all pixels in the camera
  MExtractedSignalCam *fSignals;           //! Extracted signal of all pixels in the camera
                                       
  MRawEvtData         *fRawEvt;            //! Raw event data (time slices)
  MRawRunHeader       *fRunHeader;         //! RunHeader information
                                       
  Byte_t   fHiGainFirst;                   // First FADC slice nr. to extract the High Gain signal
  Byte_t   fHiGainLast;                    // Last FADC slice nr. to extract the High Gain signal
  Byte_t   fLoGainFirst;                   // First FADC slice nr. to extract the Low Gain signal
  Byte_t   fLoGainLast;                    // Last FADC slice nr. to extract the Low Gain signal
                                           
  Byte_t   fHiLoLast;                      // Number of slices in fLoGainSamples counted for the High-Gain signal
                                           
  Float_t  fNumHiGainSamples;              // Number High Gain FADC slices used to extract the signal
  Float_t  fNumLoGainSamples;              // Number Low  Gain FADC slices used to extract the signal
                                           
  Float_t  fSqrtHiGainSamples;             // Sqrt. nr. High Gain FADC slices used to extract the signal
  Float_t  fSqrtLoGainSamples;             // Sqrt. nr. Low  Gain FADC slices used to extract the signal
                                           
  Byte_t   fSaturationLimit;               // Highest FADC slice value until being declared saturated
  TString  fNamePedestalCam;              // Name of the 'MPedestalCam' container
  
  virtual void FindSignalHiGain(Byte_t *firstused, Byte_t *lowgain, Float_t &sum, Byte_t &sat) const { }
  virtual void FindSignalLoGain(Byte_t *firstused, Float_t &sum, Byte_t &sat) const { }
  
  Int_t   PreProcess(MParList *pList);
  Bool_t  ReInit(MParList *pList);
  Int_t   Process();
  void    StreamPrimitive(ofstream &out) const;
  Int_t   ReadEnv(const TEnv &env, TString prefix, Bool_t print);

public:
  MExtractor(const char *name=NULL, const char *title=NULL);
  
  Byte_t  GetHiGainFirst()      const { return fHiGainFirst;      }
  Byte_t  GetHiGainLast ()      const { return fHiGainLast ;      }
  Byte_t  GetLoGainFirst()      const { return fLoGainFirst;      }
  Byte_t  GetLoGainLast ()      const { return fLoGainLast ;      }
  Float_t GetNumHiGainSamples() const { return fNumHiGainSamples; }
  Float_t GetNumLoGainSamples() const { return fNumLoGainSamples; }
  
  virtual void SetRange    ( Byte_t hifirst=0, Byte_t hilast=0, Byte_t lofirst=0, Byte_t lolast=0 );

  void SetOffsetLoGain ( const Float_t f=fgOffsetLoGain) { fOffsetLoGain = f; }
  void SetSaturationLimit  ( Byte_t       lim=fgSaturationLimit        ) { fSaturationLimit  = lim;  }
  void SetNamePedestalCam ( const char *name=fgNamePedestalCam.Data()) { fNamePedestalCam = name; }

  void Print(Option_t *o="") const;

  ClassDef(MExtractor, 2) // Signal Extractor Base Class
};

#endif
