#ifndef MARS_MCalibrationChargeCalc
#define MARS_MCalibrationChargeCalc

/////////////////////////////////////////////////////////////////////////////
//                                                                         //
// MCalibrationChargeCalc                                                   //
//                                                                         //
// Integrates the time slices of the all pixels of a calibration event     //
// and substract the pedestal value                                        //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////

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

#ifndef MARS_MBadPixelsPix
#include "MBadPixelsPix.h"
#endif

#ifndef MARS_MCalibrationCam
#include "MCalibrationCam.h"
#endif

class MRawEvtData;
class MRawRunHeader;
class MPedestalCam;
class MPedestalPix;
class MCalibrationChargePINDiode;
class MCalibrationChargeBlindPix;
class MCalibrationChargePix;
class MCalibrationChargeCam;
class MCalibrationQECam;
class MGeomCam;
class MExtractedSignalCam;
class MExtractedSignalBlindPixel;
class MExtractedSignalPINDiode;
class MBadPixelsCam;
class MBadPixelsPix;
class MTime;
class MCalibrationChargeCalc : public MTask
{
private:

  static const Float_t fgChargeLimit;            //! Default for fChargeLimit            (now set to: 2.5)
  static const Float_t fgChargeErrLimit;         //! Default for fChargeErrLimit         (now set to: 0.)
  static const Float_t fgChargeRelErrLimit;      //! Default for fChargeRelErrLimit      (now set to: 1.)
  static const Float_t fgLambdaCheckLimit;       //! Default for fLambdaCheckLimit       (now set to: 0.2)
  static const Float_t fgLambdaErrLimit;         //! Default for fLabmdaErrLimit         (now set to: 0.2)
  static const Float_t fgPheErrLimit;            //! Default for fPheErrLimit            (now set to: 4.)
  static const Float_t fgFFactorErrLimit;        //! Default for fFFactorErrLimit        (now set to: 3.)
 
  // Variables
  Float_t fChargeLimit;                        // Limit acceptance mean charge  (in units of PedRMS)
  Float_t fChargeErrLimit;                     // Limit acceptance charge error (in abs. numbers)
  Float_t fChargeRelErrLimit;                  // Limit acceptance rel. error mean (in abs. numbers)
  Byte_t  fFlags;                              // Bit-field for the flags
  Float_t fLambdaCheckLimit;                   // Limit rel. diff. lambda and lambdacheck in Blind Pixel
  Float_t fLambdaErrLimit;                     // Limit acceptance lambda error in Blind Pixel
  Float_t fNumHiGainSamples;                   // Number High-Gain FADC slices used by extractor
  Float_t fNumLoGainSamples;                   // Number Low -Gain FADC slices used by extractor
  Float_t fPheErrLimit;                        // Limit acceptance nr. phe's w.r.t. area idx mean (in sigmas)
  Float_t fFFactorErrLimit;                    // Limit acceptance F-Factor w.r.t. area idx mean 
  Float_t fSqrtHiGainSamples;                  // Square root nr. High-Gain FADC slices used by extractor
  Float_t fSqrtLoGainSamples;                  // Square root nr. Low -Gain FADC slices used by extractor 
  MCalibrationCam::PulserColor_t fPulserColor; // Calibration LEDs colour 
  Int_t   fNumInnerFFactorMethodUsed;          // Number of inner pixels used for F-Factor Method calibration
  
  TString fOutputPath;                         // Path to the output file
  TString fOutputFile;                         // Name of the output file  
  
  // Pointers
  MBadPixelsCam              *fBadPixels;      //  Bad Pixels 
  MCalibrationChargeCam      *fCam;            //  Calibrated Charges of all pixels 
  MCalibrationChargeBlindPix *fBlindPixel;     //  Calibrated Charges of the Blind Pixel 
  MCalibrationChargePINDiode *fPINDiode;       //  Calibrated Charges of the PIN Diode
  MCalibrationQECam          *fQECam;          //  Calibrated Quantum Efficiencies of all pixels 
  MGeomCam                   *fGeom;           //! Camera geometry
  MPedestalCam               *fPedestals;      //! Pedestals all pixels (calculated previously from ped.file)
  MTime                      *fEvtTime;        //! Time of the event

  // enums
  enum  { kHiLoGainCalibration, kDebug };

  // functions
  const char* GetOutputFile();
  void   FinalizePedestals      ( const MPedestalPix &ped, MCalibrationChargePix &cal, const Int_t aidx );
  Bool_t FinalizeCharges        ( MCalibrationChargePix &cal, MBadPixelsPix &bad      );
  Bool_t FinalizePINDiode       ();
  Bool_t FinalizeBlindPixel     ();
  Bool_t FinalizeFFactorMethod  ();
  void   FinalizeBadPixels      ();
  void   FinalizeFFactorQECam   ();  
  void   FinalizeBlindPixelQECam();
  void   FinalizePINDiodeQECam  ();
  void   FinalizeUnsuitablePixels();

  void   PrintUncalibrated( MBadPixelsPix::UncalibratedType_t typ, const char *text) const;

  Int_t  PreProcess (MParList *pList);
  Bool_t ReInit     (MParList *pList); 
  Int_t  Process    ();
  Int_t  PostProcess();

public:

  MCalibrationChargeCalc(const char *name=NULL, const char *title=NULL);

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

  Bool_t IsDebug() const   {  return TESTBIT(fFlags,kDebug); }
  
  void SetChargeLimit       ( const Float_t f=fgChargeLimit            ) { fChargeLimit       = f;   }
  void SetChargeErrLimit    ( const Float_t f=fgChargeErrLimit         ) { fChargeErrLimit    = f;   }
  void SetChargeRelErrLimit ( const Float_t f=fgChargeRelErrLimit      ) { fChargeRelErrLimit = f;   }
  void SetFFactorErrLimit   ( const Float_t f=fgFFactorErrLimit        ) { fFFactorErrLimit   = f;   }
  void SetLambdaErrLimit    ( const Float_t f=fgLambdaErrLimit         ) { fLambdaErrLimit    = f;   }
  void SetLambdaCheckLimit  ( const Float_t f=fgLambdaCheckLimit       ) { fLambdaCheckLimit  = f;   }
  void SetOutputPath        ( TString path="."                   );
  void SetOutputFile        ( TString file="ChargeCalibStat.txt" );
  void SetPheErrLimit       ( const Float_t f=fgPheErrLimit            ) { fPheErrLimit       = f;   }  
  void SetPulserColor       ( const MCalibrationCam::PulserColor_t col ) { fPulserColor       = col; }

  void SkipHiLoGainCalibration ( const Bool_t b=kTRUE )
      { b ? CLRBIT(fFlags, kHiLoGainCalibration) : SETBIT(fFlags, kHiLoGainCalibration); }
  void SetDebug              ( const Bool_t b=kTRUE )
      { b ? CLRBIT(fFlags, kDebug              ) : SETBIT(fFlags, kDebug              ); }

  ClassDef(MCalibrationChargeCalc, 1)   // Task calculating Calibration Containers and Quantum Efficiencies
};

#endif
