#ifndef MARS_MJPedestal
#define MARS_MJPedestal

#ifndef MARS_MJob
#include "MJob.h"
#endif
#ifndef MARS_MPedestalCam
#include "MPedestalCam.h"
#endif
#ifndef MARS_MBadPixelsCam
#include "MBadPixelsCam.h"
#endif

class TCanvas;
class MParList;
class MRunIter;
class MHCamera;
class TH1D;
class MExtractor;
class MEvtLoop;

class MJPedestal : public MJob
{
private:

  static const Double_t fgPedestalMin;                 //! Minimum Axis value for pedestal datacheck display
  static const Double_t fgPedestalMax;                 //! Maximum Axis value for pedestal datacheck display
  static const Double_t fgPedRmsMin;                   //! Minimum Axis value for ped. RMS datacheck display
  static const Double_t fgPedRmsMax;                   //! Maximum Axis value for ped. RMS datacheck display
  
  static const Float_t  fgRefPedClosedLids;            //! Reference line pedestal for closed lids run
  static const Float_t  fgRefPedExtraGalactic;         //! Reference line pedestal for extragalactic source
  static const Float_t  fgRefPedGalactic;              //! Reference line pedestal for galactic source     
  
  static const Float_t  fgRefPedRmsClosedLidsInner;    //! Ref. line ped. RMS for closed lids run - inner pixels     
  static const Float_t  fgRefPedRmsExtraGalacticInner; //! Ref. line ped. RMS for extragalactic source - inner pixels 
  static const Float_t  fgRefPedRmsGalacticInner;      //! Ref. line ped. RMS for galactic source - inner pixels     
  
  static const Float_t  fgRefPedRmsClosedLidsOuter;    //! Ref. line ped. RMS for closed lids run - outer pixels     
  static const Float_t  fgRefPedRmsExtraGalacticOuter; //! Ref. line ped. RMS for extragalactic source - outer pixels
  static const Float_t  fgRefPedRmsGalacticOuter;      //! Ref. line ped. RMS for galactic source - outer pixels     
    
  static const TString  fgNameExtractorCam;            //! "ExtractorResolution"

  MRunIter   *fRuns;                                   // Used pedestal runs
  MExtractor *fExtractor;                              // Signal extractor, used to find the nr. of used FADC slices
  
  MPedestalCam  fPedestalCamIn;                        // Handed over pedestal results
  MPedestalCam  fPedestalCamOut;                       // Created pedestal results
  MBadPixelsCam fBadPixels;                            // Bad Pixels

  TString fNameExtractorCam;                           // Name of the outgoing MPedestalCam if fExtractorResolution
  
  enum Display_t {kDataCheckDisplay, kNormalDisplay};  // Possible Display types
  Display_t fDisplayType;                              // Chosen Display type    
  
  enum Storage_t { kNoStorage };                       // Possible flags for the storage of results
  Byte_t fStorage;                                     // Bit-field for chosen storage type
    
  Bool_t fDataCheck;                                   // Flag if the data check is run on raw data

  enum Extract_t {kUseData, kUsePedRun, kUseHists };   // Possible flags for the extraction of the pedestal
  Extract_t fExtractType;                              // Chosen extractor type

  Bool_t fExtractorResolution;                         // Flag if the extractor is used to calculate the pedestals
  
  MExtractor *ReadCalibration() const;
  Bool_t ReadPedestalCam();
  Bool_t WriteResult();
  //Bool_t WriteEventloop(MEvtLoop &evtloop) const;

  void   DisplayResult(MParList &plist);
  void   DisplayReferenceLines(MHCamera *cam, const Int_t what) const;
  void   DisplayOutliers(TH1D *hist) const;
  void   FixDataCheckHist(TH1D *hist) const;
  
  Bool_t IsNoStorage() const { return TESTBIT(fStorage, kNoStorage); }
  
  Bool_t CheckEnvLocal();
    
public:

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

  MPedestalCam &GetPedestalCam()            { return fPedestalCamOut; }
  const MBadPixelsCam &GetBadPixels() const { return fBadPixels;   }
  
  const char*  GetNameExtractorCam()  const { return fNameExtractorCam.Data(); }
  const char*  GetOutputFile()        const;

  const Bool_t IsDataCheck()          const { return fDataCheck; }
  const Bool_t IsUseData()            const { return fExtractType == kUseData; }
  
  Bool_t Process    ();
  Bool_t ProcessFile();
  
  void SetBadPixels(const MBadPixelsCam &bad) { bad.Copy(fBadPixels); }
  void SetPedestals(const MPedestalCam  &ped) { ped.Copy(fPedestalCamIn); }  
  void SetExtractor(MExtractor* ext)          { fExtractor = ext;     }
  void SetInput(MRunIter  *iter)              { fRuns      = iter;    }
  void SetUseData()                           { fExtractType = kUseData;   }
  void SetUseHists()                          { fExtractType = kUseHists;  }
  void SetUsePedRun()                         { fExtractType = kUsePedRun; }
  void SetDataCheck(const Bool_t b=kTRUE)     { fDataCheck = b; b ? SetDataCheckDisplay() : SetNormalDisplay(); }
  void SetDataCheckDisplay()                  { fDisplayType = kDataCheckDisplay; }
  void SetNormalDisplay()                     { fDisplayType = kNormalDisplay;    }
  void SetExtractorResolution(const Bool_t b=kTRUE) { fExtractorResolution = b;  }
  void SetNameExtractorCam( const char* name= fgNameExtractorCam.Data())  { fNameExtractorCam = name;  }
  
  
  // Storage
  void SetNoStorage(const Bool_t b)           { b ? SETBIT(fStorage, kNoStorage) : CLRBIT(fStorage,kNoStorage); }
  void SetNormalStorage()                     { CLRBIT(fStorage, kNoStorage); }
  
  ClassDef(MJPedestal, 0) // Tool to create a pedestal file (MPedestalCam)
};

#endif
