#ifndef MARS_MBadPixelsPix
#define MARS_MBadPixelsPix

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

#ifndef ROOT_TArrayI
#include <TArrayI.h>
#endif

class MBadPixelsPix : public MParContainer
{
private:
    TArrayI fInfo;

public:
    MBadPixelsPix(const char* name=NULL, const char* title=NULL);

    enum UnsuitableType_t {
        kUnsuitableRun    = BIT(1),
        kUnsuitableEvt    = BIT(2),
        kUnreliableRun    = BIT(3)
    };

    // All types are initialized to normal behaviour
    enum CalibrationType_t {
      kHiGainSaturation         = BIT(1),
      kLoGainSaturation         = BIT(2),
      kHiGainNotFitted          = BIT(3),
      kLoGainNotFitted          = BIT(4), 
      kChargeIsPedestal         = BIT(5),
      kChargeErrNotValid        = BIT(6),
      kChargeRelErrNotValid     = BIT(7),
      kChargeSigmaNotValid      = BIT(8),
      kConvHiLoNotValid         = BIT(9),      
      kHiGainOscillating        = BIT(10),
      kLoGainOscillating        = BIT(11),
      kMeanTimeInFirstBin       = BIT(12),
      kMeanTimeInLastBin        = BIT(13), 
      kBlindPixelMethodNotValid = BIT(14),
      kFFactorMethodNotValid    = BIT(15), 
      kPINDiodeMethodNotValid   = BIT(16),
      kCombinedMethodNotValid   = BIT(17)
    };
    
      
    static const Int_t fgRunMask; // All types which are not event wise determined

    void Reset();
    void Clear(Option_t *o="");
    void Copy(TObject &object) const
    {
        static_cast<MBadPixelsPix&>(object).fInfo = fInfo;
    }

    // Setter
    void   SetUnsuitableRun(UnsuitableType_t typ=kUnsuitableRun) { fInfo[0] |=  typ; }
    void   SetSuitableRun(UnsuitableType_t typ=kUnsuitableRun)   { fInfo[0] &= ~typ; }

    void   SetUnsuitableEvt(UnsuitableType_t typ=kUnsuitableEvt) { fInfo[0] |=  typ; }
    void   SetSuitableEvt(UnsuitableType_t typ=kUnsuitableEvt)   { fInfo[0] &= ~typ; }

    void   SetUnreliableRun(UnsuitableType_t typ=kUnreliableRun) { fInfo[0] |=  typ; }
    void   SetReliableRun(UnsuitableType_t typ=kUnreliableRun)   { fInfo[0] &= ~typ; }

    // Calibration
    void SetHiGainSaturation         ( CalibrationType_t typ=kHiGainSaturation         )
      { fInfo[1] |= typ; }
    void SetLoGainSaturation         ( CalibrationType_t typ=kLoGainSaturation         )
      { fInfo[1] |= typ; }
    void SetCombinedMethodNotValid   ( CalibrationType_t typ=kCombinedMethodNotValid   )
      { fInfo[1] |= typ; }
    void SetPINDiodeMethodNotValid   ( CalibrationType_t typ=kPINDiodeMethodNotValid   )
      { fInfo[1] |= typ; }
    void SetFFactorMethodNotValid    ( CalibrationType_t typ=kFFactorMethodNotValid    )
      { fInfo[1] |= typ; }
    void SetBlindPixelMethodNotValid ( CalibrationType_t typ=kBlindPixelMethodNotValid )
      { fInfo[1] |= typ; }
    void SetMeanTimeInLastBin        ( CalibrationType_t typ=kMeanTimeInLastBin        )
      { fInfo[1] |= typ; }
    void SetMeanTimeInFirstBin       ( CalibrationType_t typ=kMeanTimeInFirstBin       )
      { fInfo[1] |= typ; }
    void SetLoGainOscillating        ( CalibrationType_t typ=kLoGainOscillating        )
      { fInfo[1] |= typ; }
    void SetHiGainOscillating        ( CalibrationType_t typ=kHiGainOscillating        )
      { fInfo[1] |= typ; }
    void SetConvHiLoNotValid         ( CalibrationType_t typ=kConvHiLoNotValid         )
      { fInfo[1] |= typ; }
    void SetChargeSigmaNotValid      ( CalibrationType_t typ=kChargeSigmaNotValid      )
      { fInfo[1] |= typ; }
    void SetChargeRelErrNotValid     ( CalibrationType_t typ=kChargeRelErrNotValid     )
      { fInfo[1] |= typ; }
    void SetChargeErrNotValid        ( CalibrationType_t typ=kChargeErrNotValid        )
      { fInfo[1] |= typ; }
    void SetChargeIsPedestal         ( CalibrationType_t typ=kChargeIsPedestal         )
      { fInfo[1] |= typ; }
    void SetLoGainNotFitted          ( CalibrationType_t typ=kLoGainNotFitted          )
      { fInfo[1] |= typ; }
    void SetHiGainNotFitted          ( CalibrationType_t typ=kHiGainNotFitted          )
      { fInfo[1] |= typ; }

    // Getter
    Bool_t IsUnsuitableRun(UnsuitableType_t typ=kUnsuitableRun) const { return   fInfo[0]&typ; }
    Bool_t IsSuitableRun(UnsuitableType_t typ=kUnsuitableRun) const   { return !(fInfo[0]&typ); }

    Bool_t IsUnsuitableEvt(UnsuitableType_t typ=kUnsuitableEvt) const { return   fInfo[0]&typ; }
    Bool_t IsSuitableEvt(UnsuitableType_t typ=kUnsuitableEvt) const   { return !(fInfo[0]&typ); }

    Bool_t IsUnreliableRun(UnsuitableType_t typ=kUnreliableRun) const { return   fInfo[0]&typ; }
    Bool_t IsReliableRun(UnsuitableType_t typ=kUnreliableRun) const   { return !(fInfo[0]&typ); }

    Bool_t IsOK() const  { return fInfo[0]==0; }
    Bool_t IsBad() const { return fInfo[0]!=0; }

    Bool_t IsHiGainSaturation         () const      { return fInfo[1] & kHiGainSaturation ;        }
    Bool_t IsLoGainSaturation         () const      { return fInfo[1] & kLoGainSaturation ;        }
    Bool_t IsCombinedMethodNotValid   () const      { return fInfo[1] & kCombinedMethodNotValid;   }
    Bool_t IsPINDiodeMethodNotValid   () const      { return fInfo[1] & kPINDiodeMethodNotValid;   }
    Bool_t IsFFactorMethodNotValid    () const      { return fInfo[1] & kFFactorMethodNotValid;    }
    Bool_t IsBlindPixelMethodNotValid () const      { return fInfo[1] & kBlindPixelMethodNotValid; }
    Bool_t IsMeanTimeInLastBin        () const      { return fInfo[1] & kMeanTimeInLastBin;        }
    Bool_t IsMeanTimeInFirstBin       () const      { return fInfo[1] & kMeanTimeInFirstBin;       }
    Bool_t IsLoGainOscillating        () const      { return fInfo[1] & kLoGainOscillating;        }
    Bool_t IsHiGainOscillating        () const      { return fInfo[1] & kHiGainOscillating;        }
    Bool_t IsConvHiLoNotValid         () const      { return fInfo[1] & kConvHiLoNotValid;         }
    Bool_t IsChargeSigmaNotValid      () const      { return fInfo[1] & kChargeSigmaNotValid;      }
    Bool_t IsChargeRelErrNotValid     () const      { return fInfo[1] & kChargeRelErrNotValid;     }
    Bool_t IsChargeErrNotValid        () const      { return fInfo[1] & kChargeErrNotValid;        }
    Bool_t IsChargeIsPedestal         () const      { return fInfo[1] & kChargeIsPedestal;         }
    Bool_t IsLoGainNotFitted          () const      { return fInfo[1] & kLoGainNotFitted;          }
    Bool_t IsHiGainNotFitted          () const      { return fInfo[1] & kHiGainNotFitted;          }

    Bool_t IsLoGainBad() const { return IsLoGainSaturation() || IsConvHiLoNotValid() || IsLoGainOscillating() ;}
    Bool_t IsHiGainBad() const { return (IsHiGainSaturation() && IsConvHiLoNotValid()) || IsHiGainOscillating(); }

    Bool_t IsCalibrationSignalOK() const  { return !( IsChargeIsPedestal()
                                                      || IsChargeErrNotValid()
                                                      || IsChargeRelErrNotValid()
                                                      || IsChargeSigmaNotValid()
                                                      || IsMeanTimeInFirstBin()
                                                      || IsMeanTimeInLastBin() );  }
    Bool_t IsCalibrationFitOK()       const    { return !( (!IsHiGainSaturation() && IsHiGainNotFitted())
                                                      || ( IsHiGainSaturation() && IsLoGainNotFitted()) ); }
    Bool_t IsCalibrationOscillating() const  { return ( !IsHiGainSaturation() && IsHiGainOscillating()) 
                                                  || ( IsHiGainSaturation() && IsLoGainOscillating()) ; }
    Bool_t IsCalibrationResultOK()    const  {  return IsCalibrationSignalOK()
                                                  && !IsCalibrationOscillating()
                                                  && IsCalibrationFitOK()
                                                  && (   (!IsHiGainSaturation() && !IsHiGainBad())
                                                       || (IsHiGainSaturation() && !IsLoGainBad()) ) ;}

    void Merge(const MBadPixelsPix &pix);

    const TArrayI &GetInfo() const { return fInfo; }

    ClassDef(MBadPixelsPix, 1)	// Storage Container for bad pixel information of a single pixel
};

#endif

