#ifndef MARS_MCalibrationPix
#define MARS_MCalibrationPix

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

#include "MHCalibrationPixel.h"

class MCalibrationPix : public MParContainer
{
private:

  static const Float_t gkElectronicPedRms;    // The pure electronic component of the RMS
  static const Float_t gkErrElectronicPedRms; // The error of the pure electronic component of the RMS
  static const Float_t gkFFactor;             // The laboratory F-factor of the PMTs
  static const Float_t gkFFactorError;        // The laboratory F-factor Error of the PMTs
  static const Float_t gkChargeLimit;         // The limit (in units of PedRMS) for acceptance of the fitted mean charge
  static const Float_t gkChargeErrLimit;      // The limit (in units of PedRMS) for acceptance of the fitted charge sigma
  static const Float_t gkChargeRelErrLimit;   // The limit (in units of Error of fitted charge) for acceptance of the fitted mean  
  static const Float_t gkTimeLimit;           // The limit (in units of FADC slices) for acceptance of the fitted time
  static const Float_t gkTimeErrLimit;        // The limit (in units of FADC slices) for acceptance of the fitted time sigma
  static const Float_t gkConvFFactorRelErrorLimit; // The limit (in units of [1]) for acceptance of the rel. error of the conversion factor with the FFactor method
  
  
  Int_t   fPixId;                     // the pixel Id

  UInt_t  fFlags;               // Flag for the set Bits
  
  Float_t fCharge;              // The mean reduced charge after the fit
  Float_t fErrCharge;           // The error of reduced mean charge after the fit
  Float_t fSigmaCharge;         // The sigma of the mean charge after the fit
  Float_t fErrSigmaCharge;      // The error of the sigma of the mean charge after the fit
  Float_t fRSigmaCharge;        // The reduced squares of sigmas after the fit
  Float_t fErrRSigmaCharge;     // The reduced squares of sigmas after the fit  
  Float_t fChargeProb;          // The probability of the fit function 

  Float_t fPed;                 // The mean pedestal (from MPedestalPix)
  Float_t fPedRms;              // The pedestal  RMS (from MPedestalPix)
  Float_t fErrPedRms;           // The error of the pedestal  RMS (from MPedestalPix)  

  Float_t fMeanTimeOffset;      // The mean relative arrival time offset after the fit
  Float_t fMeanTimeOffsetError; // The mean relative arrival time offset error after the fit    
  Float_t fTimingPrecision;     // The error of the mean arrival time after the fit
  Float_t fTimeProb;            // The probability of the fit function 

  Float_t fAbsTimeMean;
  Float_t fAbsTimeMeanErr;  
  Float_t fAbsTimeRms;
  
  Byte_t  fTimeFirstHiGain;           // The first used FADC slice
  Byte_t  fTimeLastHiGain;            // The last used FADC slice
  
  Byte_t  fTimeFirstLoGain;           // The first used FADC slice
  Byte_t  fTimeLastLoGain;            // The last used FADC slice
  
  Float_t fPheFFactorMethod;                // The number of Phe's calculated (F-factor method)
  Float_t fPheFFactorMethodError;           // The error on the number of Phe's calculated (F-factor method)

  Float_t fMeanConversionFFactorMethod;     // The conversion factor to Phe's (F-factor method)
  Float_t fMeanConversionBlindPixelMethod;  // The conversion factor to Ph's (Blind Pixel method)
  Float_t fMeanConversionPINDiodeMethod;    // The conversion factor to Ph's (PIN Diode method)

  Float_t fErrorConversionFFactorMethod;    // The error of the conversion factor to Phe's (F-factor method)
  Float_t fErrorConversionBlindPixelMethod; // The error of the conversion factor to Ph's (Blind Pixel method)
  Float_t fErrorConversionPINDiodeMethod;   // The error of the conversion factor to Ph's (PIN Diode method)

  Float_t fSigmaConversionFFactorMethod;    // The sigma of conversion factor to Phe's (F-factor method)
  Float_t fSigmaConversionBlindPixelMethod; // The conversion factor to Ph's (Blind Pixel method)
  Float_t fSigmaConversionPINDiodeMethod;   // The conversion factor to Ph's (PIN Diode method)

  Float_t fTotalFFactor;                    // The F-Factor of the total readout system (Sigma(out)/mean(out)*Mean(in)/sigma(in)
  Float_t fTotalFFactorError;               // The error on the F-Factor of the total readout system
  
  Float_t fConversionHiLo;                  // The conversion factor between Hi Gain and Lo Gain  
  Float_t fConversionHiLoError;             // The error of the conversion factor between Hi Gain and Lo Gain  

  Float_t fNumHiGainSamples;
  Float_t fNumLoGainSamples;
  
  Bool_t fFactorCalculated;
  
  enum  { kHiGainSaturation,
          kExcluded, kExcludeQualityCheck,
          kChargeFitValid, kTimeFitValid,
          kFitted,
          kBlindPixelMethodValid, kFFactorMethodValid, kPINDiodeMethodValid };
  
  MHCalibrationPixel *fHist;                // Pointer to the histograms performing the fits, etc.  

  Bool_t CheckChargeFitValidity();
  Bool_t CheckTimeFitValidity();
  Bool_t CheckOscillations();  

  Bool_t CalcFFactorMethod();
  
public:

  MCalibrationPix(const char *name=NULL, const char *title=NULL);
  ~MCalibrationPix();
  
  void Clear(Option_t *o="");

  // Getter
  MHCalibrationPixel *GetHist() const   { return fHist;     }

  // Charges
  Float_t GetCharge()              const { return fCharge;          }
  Float_t GetErrCharge()           const { return fErrCharge;       }
  Float_t GetChargeProb()          const { return fChargeProb;      }    
  Float_t GetSigmaCharge()         const { return fSigmaCharge;     }
  Float_t GetErrSigmaCharge()      const { return fErrSigmaCharge;  }
  Float_t GetRSigmaCharge()        const { return fRSigmaCharge;    }
  Float_t GetErrRSigmaCharge()     const { return fErrRSigmaCharge; }  

  // Times  
  Float_t GetMeanTimeOffset()       const { return fMeanTimeOffset;      } 
  Float_t GetMeanTimeOffsetError()  const { return fMeanTimeOffsetError; }  
  Float_t GetTimingPrecision()      const { return fTimingPrecision;     }
  Float_t GetTimingPrecisionError() const;
  Float_t GetTimeProb()             const { return fTimeProb;            }      

  Float_t GetAbsTimeMean()         const { return fAbsTimeMean;    }
  Float_t GetAbsTimeMeanErr()      const { return fAbsTimeMeanErr; }
  Float_t GetAbsTimeRms()          const { return fAbsTimeRms;     }
  
  // Conversion Factors
  Float_t GetConversionHiLo()                 const  { return fConversionHiLo;        }
  Float_t GetConversionHiLoError()            const  { return fConversionHiLoError;   }

  Float_t GetMeanConversionBlindPixelMethod()  const { return fMeanConversionBlindPixelMethod  ; }
  Float_t GetErrorConversionBlindPixelMethod() const { return fErrorConversionBlindPixelMethod ; }
  Float_t GetSigmaConversionBlindPixelMethod() const { return fSigmaConversionBlindPixelMethod ; }

  Float_t GetMeanConversionFFactorMethod();
  Float_t GetErrorConversionFFactorMethod();
  Float_t GetSigmaConversionFFactorMethod();

  Float_t GetMeanConversionPINDiodeMethod()    const { return fMeanConversionPINDiodeMethod ;  }
  Float_t GetErrorConversionPINDiodeMethod()   const { return fErrorConversionPINDiodeMethod ; }
  Float_t GetSigmaConversionPINDiodeMethod()   const { return fSigmaConversionPINDiodeMethod ; }

  Float_t GetPheFFactorMethod();    
  Float_t GetPheFFactorMethodError();

  Int_t   GetPixId()                           const  { return fPixId;   }

  Float_t GetPed()                             const { return fPed;    }
  Float_t GetPedRms()                          const { return fPedRms; }

  Float_t GetTotalFFactor();
  Float_t GetTotalFFactorError();
  
  Bool_t IsExcluded()              const;
  Bool_t IsChargeFitValid()        const;
  Bool_t IsTimeFitValid()          const;
  Bool_t IsFitted()                const;
  Bool_t IsBlindPixelMethodValid() const;
  Bool_t IsPINDiodeMethodValid()   const;
  Bool_t IsFFactorMethodValid();

  // Setter
  void SetPedestal(Float_t ped, Float_t pedrms, Float_t higainsamp, Float_t logainsamp);
  void SetConversionHiLo(Float_t c)      { fConversionHiLo      = c;    }
  void SetConversionHiLoError(Float_t e)  { fConversionHiLoError = e;    }

  // Setters for MC
  void SetConversionFFactorMethod(Float_t c, Float_t err, Float_t sig);
  void SetConversionBlindPixelMethod(Float_t c, Float_t err, Float_t sig);
  void SetConversionPINDiodeMethod(Float_t c, Float_t err, Float_t sig);

  // Bit Setters
  void SetHiGainSaturation(Bool_t b = kTRUE);
  void SetExcluded(Bool_t b = kTRUE);
  void SetExcludeQualityCheck(Bool_t b = kTRUE);
  void SetChargeFitValid(Bool_t b = kTRUE);
  void SetTimeFitValid(Bool_t b = kTRUE);
  void SetFitted(Bool_t b = kTRUE);
  void SetBlindPixelMethodValid(Bool_t b = kTRUE);
  void SetFFactorMethodValid(Bool_t b = kTRUE);
  void SetPINDiodeMethodValid(Bool_t b = kTRUE);
  void SetAbsTimeBordersHiGain(Byte_t f, Byte_t l);
  void SetAbsTimeBordersLoGain(Byte_t f, Byte_t l);
  
  // Fill histos
  Bool_t FillChargeHiGain(Float_t q)                  const { return fHist->FillChargeHiGain(q); }
  Bool_t FillAbsTimeHiGain(Float_t t)                 const { return fHist->FillAbsTimeHiGain(t); }
  Bool_t FillRelTimeHiGain(Float_t t)                 const { return fHist->FillRelTimeHiGain(t); }  
  Bool_t FillRChargevsTimeHiGain(Float_t rq, Int_t t) const { return fHist->FillChargevsNHiGain(rq,t); }    

  Bool_t FillChargeLoGain(Float_t q)                  const { return fHist->FillChargeLoGain(q); }
  Bool_t FillAbsTimeLoGain(Float_t t)                 const { return fHist->FillAbsTimeLoGain(t); }
  Bool_t FillRelTimeLoGain(Float_t t)                 const { return fHist->FillRelTimeLoGain(t); }    
  Bool_t FillRChargevsTimeLoGain(Float_t rq, Int_t t) const { return fHist->FillChargevsNLoGain(rq,t); }    
  
  Bool_t FillChargesInGraph(Float_t qhi,Float_t qlo) const  { return fHist->FillPointInGraph(qhi,qlo); }

  void   DefinePixId(Int_t i);

  // Fits
  Bool_t FitCharge();
  Bool_t FitTime();
  
  // Draws
  void Draw(Option_t *opt="")                    { fHist->Draw(opt); }
  TObject *DrawClone(Option_t *opt="") const    { return fHist->DrawClone(opt); }  
  
  // Miscellaneous
  void   ApplyLoGainConversion();

  ClassDef(MCalibrationPix, 1)	// Storage Container for Calibration information of one pixel
};

#endif

