#ifndef MARS_MCalibrationChargeCam
#define MARS_MCalibrationChargeCam

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

class TH1D;
class TH2D;
class TClonesArray;

class MCalibrationBlindPix;
class MCalibrationChargePINDiode;
class MCalibrationChargePix;
class MCalibrationChargeCam : public MParContainer, public MCamEvent
{
private:
  
  static const Int_t   gkBlindPixelId;
  static const Int_t   gkPINDiodeId;
  static const Float_t gkBlindPixelArea;       // The Blind Pixel area in mm^2

  static const Float_t gkCalibrationBlindPixelQEGreen;
  static const Float_t gkCalibrationBlindPixelQEBlue ;
  static const Float_t gkCalibrationBlindPixelQEUV   ;
  static const Float_t gkCalibrationBlindPixelQECT1  ;

  static const Float_t gkCalibrationBlindPixelQEGreenErr;
  static const Float_t gkCalibrationBlindPixelQEBlueErr ;
  static const Float_t gkCalibrationBlindPixelQEUVErr   ;
  static const Float_t gkCalibrationBlindPixelQECT1Err  ;
 
  static const Float_t gkCalibrationBlindPixelAttGreen;
  static const Float_t gkCalibrationBlindPixelAttBlue ;
  static const Float_t gkCalibrationBlindPixelAttUV   ;
  static const Float_t gkCalibrationBlindPixelAttCT1  ;

  Int_t fNumPixels;
  TClonesArray *fPixels;                                        //-> Array of MCalibrationPix with fit results
  
  MCalibrationBlindPix       *fBlindPixel;                      //-> Pointer to the Blind Pixel with fit results
  const MCalibrationChargePINDiode *fPINDiode;                  //! Pointer to the PIN Diode with fit results

  const MGeomCam             *fGeomCam;                         //! Need geom cam to know which pixel in inner or outer

  TH1D* fOffsets;                                               //! 
  TH1D* fSlopes;                                                //! 
  
  TH2D* fOffvsSlope;                                            //! 

  Float_t fMeanFluxInsidePlexiglass;          //  The mean number of photons in an INNER PIXEL inside the plexiglass
  Float_t fMeanFluxErrInsidePlexiglass;       //  The uncertainty about the number of photons in an INNER PIXEL  

  UInt_t  fNumExcludedPixels;

  Byte_t  fFlags;

  enum  { kBlindPixelMethodValid, kPINDiodeMethodValid, kCombinedMethodValid, 
          kFluxInsidePlexiglassAvailable };
  
public:

  enum PulserColor_t { kEBlue, kEGreen, kEUV, kECT1 } ;

private:

  PulserColor_t fColor;  
  
public:

  MCalibrationChargeCam(const char *name=NULL, const char *title=NULL);
  ~MCalibrationChargeCam();
  
  void Clear(    Option_t *o="" );
  void InitSize( const UInt_t i );

  // Setters   
  void SetColor(    const PulserColor_t color )           {  fColor = color;         }
  void SetNumPixelsExcluded(  const UInt_t n )            {  fNumExcludedPixels = n; }
  void SetGeomCam(  const MGeomCam *geom)                 {  fGeomCam = geom;        }
  void SetPINDiode( const MCalibrationChargePINDiode *d ) {  fPINDiode = d;          }

  // Setters only for MC!!
  void SetBlindPixelMethodValid( const Bool_t b = kTRUE );
  void SetPINDiodeMethodValid(   const Bool_t b = kTRUE );  

  // Getters
  Int_t GetSize()                                  const;
  UInt_t GetNumPixels()                            const { return fNumPixels; }

  MCalibrationBlindPix *GetBlindPixel()                  { return fBlindPixel;  }
  const MCalibrationBlindPix *GetBlindPixel()      const { return fBlindPixel;  }

  Float_t GetMeanFluxInsidePlexiglass()     const { return fMeanFluxInsidePlexiglass;     }
  Float_t GetMeanFluxErrInsidePlexiglass()  const { return fMeanFluxErrInsidePlexiglass;  }

  Bool_t GetConversionFactorFFactor(    Int_t ipx, Float_t &mean, Float_t &err, Float_t &sigma );
  Bool_t GetConversionFactorBlindPixel( Int_t ipx, Float_t &mean, Float_t &err, Float_t &sigma );
  Bool_t GetConversionFactorPINDiode(   Int_t ipx, Float_t &mean, Float_t &err, Float_t &sigma );
  Bool_t GetConversionFactorCombined(   Int_t ipx, Float_t &mean, Float_t &err, Float_t &sigma );

  Bool_t IsBlindPixelMethodValid()   const;
  Bool_t IsPINDiodeMethodValid()     const;  

  Bool_t IsFluxInsidePlexiglassAvailable()  const;

  // Others
  MCalibrationChargePix &operator[](UInt_t i);
  const MCalibrationChargePix &operator[](UInt_t i) const;
  
  void CutEdges();
  Bool_t CheckBounds(Int_t i) const;

  // Prints
  void Print(Option_t *o="") const;
  
  // Draws
  void DrawPixelContent(Int_t num) const;    
//  void DrawHiLoFits();
  
  // Others
  Bool_t GetPixelContent(Double_t &val, Int_t idx, const MGeomCam &cam, Int_t type=0) const;

  Bool_t CalcFluxInsidePlexiglass();
  void   ApplyPINDiodeCalibration();

  ClassDef(MCalibrationChargeCam, 1)	// Container for calibration information of the camera
};

#endif



