#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),
        kUnsuitable    = kUnsuitableRun|kUnsuitableEvt,
        kUnreliableRun = BIT(3),
        kUnreliableEvt = BIT(4),
        kUnreliable    = kUnreliableRun|kUnreliableEvt
    };

    static const Int_t fgRunMask; // All types which are not event wise determined

    // All types are initialized to normal behaviour
    enum UncalibratedType_t {
      kHiGainNotFitted          = BIT(1),
      kLoGainNotFitted          = BIT(2), 
      kRelTimeNotFitted         = BIT(3),
      kHiGainOscillating        = BIT(4),
      kLoGainOscillating        = BIT(5),
      kRelTimeOscillating       = BIT(6),
      kLoGainSaturation         = BIT(7),
      kChargeIsPedestal         = BIT(8),
      kChargeErrNotValid        = BIT(9),
      kChargeRelErrNotValid     = BIT(10),
      kChargeSigmaNotValid      = BIT(11),
      kMeanTimeInFirstBin       = BIT(12),
      kMeanTimeInLast2Bins      = BIT(13), 
      kDeviatingNumPhes         = BIT(14),
      kDeviatingNumPhots        = BIT(15),
      kDeviatingFFactor         = BIT(16),
      kDeviatingTimeResolution  = BIT(17),
      kConversionHiLoNotValid   = BIT(18),
      kHiGainOverFlow           = BIT(19),
      kLoGainOverFlow           = BIT(20)
    };
    
    // This is just a start..
    enum HardwareType_t {
      kHVNotNominal             = BIT(1)
    };
    
      
    void Reset();
    void Clear(Option_t *o="");
    void Copy(TObject &object) const
    {
        static_cast<MBadPixelsPix&>(object).fInfo = fInfo;
    }

    // Setter
    void SetUnsuitable  (UnsuitableType_t   typ) { fInfo[0] |= typ; }
    void SetUncalibrated(UncalibratedType_t typ) { fInfo[1] |= typ; }
    void SetHardware    (HardwareType_t     typ) { fInfo[2] |= typ; }

    // Getter
    Bool_t IsUnsuitable  (UnsuitableType_t   typ) const { return fInfo[0]&typ; }
    Bool_t IsUncalibrated(UncalibratedType_t typ) const { return fInfo[1]&typ; }
    Bool_t IsHardwareBad (HardwareType_t     typ) const { return fInfo[2]&typ; }

    Bool_t IsUnsuitable() const { return fInfo[0]&kUnsuitable; }
    Bool_t IsUnreliable() const { return fInfo[0]&kUnreliable; }

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

    Bool_t IsLoGainBad() const { return IsUnsuitable  (kUnsuitableRun      )
				     || IsUncalibrated(kLoGainSaturation   ) 
				     || IsUncalibrated(kConversionHiLoNotValid) 
				     || IsUncalibrated(kLoGainOscillating  ) ; }
    Bool_t IsHiGainBad() const { return IsUnsuitable  (kUnsuitableRun      )
  				     || IsUncalibrated(kHiGainOscillating  ) ; }

    Int_t  GetUnsuitableCalibration() const   {
      if (!IsUnsuitable())                        return 0;
      if (IsUncalibrated( kChargeIsPedestal    )) return 1;
      if (IsUncalibrated( kChargeRelErrNotValid)) return 2;
      if (IsUncalibrated( kLoGainSaturation    )) return 3;
      if (IsUncalibrated( kMeanTimeInFirstBin  )) return 4;
      if (IsUncalibrated( kMeanTimeInLast2Bins )) return 5;
      if (IsUncalibrated( kDeviatingNumPhes    )) return 6;
      if (IsUncalibrated( kDeviatingFFactor    )) return 7;
      if (IsUncalibrated( kDeviatingNumPhots   )) return 8;
      if (IsUncalibrated( kHiGainOverFlow      )) return 9;
      if (IsUncalibrated( kLoGainOverFlow      )) return 10;
      return 11;
    }
    
    Int_t  GetUnreliableCalibration() const   {
      if (!IsUnreliable() || IsUnsuitable())      return 0;
      if (IsUncalibrated( kChargeSigmaNotValid )) return 1;
      if (IsUncalibrated( kHiGainNotFitted     )) return 2;
      if (IsUncalibrated( kLoGainNotFitted     )) return 3;
      if (IsUncalibrated( kRelTimeNotFitted    )) return 4;
      if (IsUncalibrated( kHiGainOscillating   )) return 5;
      if (IsUncalibrated( kLoGainOscillating   )) return 6;
      if (IsUncalibrated( kRelTimeOscillating  )) return 7;
      return 8;
    }
    
        
    
    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

