#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 MExtractPedestal;
class MEvtLoop;

class MJPedestal : public MJob
{
private:

    static const TString  fgReferenceFile;   //! default for fReferenceFile ("PedestalRef.rc")

    Axis_t fPedestalMin;                     //! Minimum Axis value for pedestal datacheck display
    Axis_t fPedestalMax;                     //! Maximum Axis value for pedestal datacheck display
    Axis_t fPedRmsMin;                       //! Minimum Axis value for ped. RMS datacheck display
    Axis_t fPedRmsMax;                       //! Maximum Axis value for ped. RMS datacheck display
				             
    Float_t fRefPedClosedLids;               //! Reference line pedestal for closed lids run
    Float_t fRefPedExtraGalactic;            //! Reference line pedestal for extragalactic source
    Float_t fRefPedGalactic;                 //! Reference line pedestal for galactic source

    Float_t fRefPedRmsClosedLidsInner;       //! Ref. line ped. RMS for closed lids run - inner pixels
    Float_t fRefPedRmsExtraGalacticInner;    //! Ref. line ped. RMS for extragalactic source - inner pixels
    Float_t fRefPedRmsGalacticInner;         //! Ref. line ped. RMS for galactic source - inner pixels

    Float_t fRefPedRmsClosedLidsOuter;       //! Ref. line ped. RMS for closed lids run - outer pixels
    Float_t fRefPedRmsExtraGalacticOuter;    //! Ref. line ped. RMS for extragalactic source - outer pixels
    Float_t fRefPedRmsGalacticOuter;         //! Ref. line ped. RMS for galactic source - outer pixels

    TString     fReferenceFile;              // File name containing the reference values

    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

    enum Display_t { kDisplayNone, kDisplayNormal, kDisplayDataCheck }; // 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

    enum Extraction { kFundamental, kWithExtractorRndm, kWithExtractor };
    Int_t fExtractionType;                   // 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();

    const char*  GetOutputFileName() const;

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

    MPedestalCam &GetPedestalCam()            { return fPedestalCamOut; }
    const MBadPixelsCam &GetBadPixels() const { return fBadPixels;   }

    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);
    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; }
    void SetDataCheckDisplay()                  { fDisplayType = kDisplayDataCheck; }
    void SetNormalDisplay()                     { fDisplayType = kDisplayNormal;    }
    void SetNoDisplay()                         { fDisplayType = kDisplayNone; }

    void SetExtractionFundamental()       { fExtractionType=kFundamental;       /*fPedestalCamOut.SetName("MPedestalFundamental");*/   }
    void SetExtractionWithExtractorRndm() { fExtractionType=kWithExtractorRndm; /*fPedestalCamOut.SetName("MPedestalExtractorRndm");*/ }
    void SetExtractionWithExtractor()     { fExtractionType=kWithExtractor;     /*fPedestalCamOut.SetName("MPedestalExtractor");*/     }

    void SetReferenceFile( const TString ref=fgReferenceFile ) { fReferenceFile = ref; }

    MExtractor *GetExtractor() const { return fExtractor; }

    // Storage
    void SetNoStorage(const Bool_t b=kTRUE)     { b ? SETBIT(fStorage, kNoStorage) : CLRBIT(fStorage,kNoStorage); }
    void SetNormalStorage()                     { CLRBIT(fStorage, kNoStorage); }

    ClassDef(MJPedestal, 0) // Tool to create a pedestal file (MPedestalCam)
};

#endif
