#ifndef MARS_MJCalibration
#define MARS_MJCalibration

#ifndef MARS_MCalibrationChargeCam
#include "MCalibrationChargeCam.h"
#endif
#ifndef MARS_MCalibrationChargeBlindPix
#include "MCalibrationChargeBlindPix.h"
#endif
#ifndef MARS_MCalibrationChargePINDiode
#include "MCalibrationChargePINDiode.h"
#endif
#ifndef MARS_MCalibrationRelTimeCam
#include "MCalibrationRelTimeCam.h"
#endif
#ifndef MARS_MCalibrationQECam
#include "MCalibrationQECam.h"
#endif
#ifndef MARS_MBadPixelsCam
#include "MBadPixelsCam.h"
#endif

class MRunIter;
class MParList;
class MPedestalCam;
class MExtractor;
class MExtractTime;
class MJCalibration : public MParContainer
{
private:

  static const Int_t gkIFAEBoxInaugurationRun;              // Run number of first IFAE box calibration

  TString fOutputPath;                                     // Path to the output files
  
  MRunIter       *fRuns;                                   // Calibration files
  MExtractor     *fExtractor;                              // Signal extractor
  MExtractTime   *fTimeExtractor;                          // Arrival Time extractor
  
  MBadPixelsCam              fBadPixels;                   // Bad Pixels cam, can be set from previous runs
  MCalibrationChargeCam      fCalibrationCam;              // Calibration conversion factors FADC2Phe
  MCalibrationChargeBlindPix fCalibrationBlindPix;         // Calibration from Blind Pixel
  MCalibrationChargePINDiode fCalibrationPINDiode;         // Calibration from PIN Diode
  MCalibrationQECam          fQECam;                       // Quantum efficiency, can be set from previous runs
  MCalibrationRelTimeCam     fRelTimeCam;                  // Calibration constants rel. times

  MCalibrationCam::PulserColor_t fColor;                   // Colour of the pulsed LEDs

  enum  Display_t   { kFullDisplay, kDataCheckDisplay, kNormalDisplay }; // Possible Display types
  
  Display_t fDisplayType;                                  // Chosen Display type

  enum  Device_t    { kUseBlindPixel, kUsePINDiode  };     // Possible devices for calibration

  Byte_t fDevices;                                         // Bit-field for used devices for calibration
  
  Bool_t fRelTimes;                                        // Flag if relative times have to be calibrated
  Bool_t fDataCheck;                                       // Flag if the data check is run on raw data
  Bool_t fDebug;

  void   DisplayResult(MParList &plist);
  Bool_t WriteResult();
  Bool_t FindColor();
  
public:

  MJCalibration(const char *name=NULL, const char *title=NULL);
  ~MJCalibration() {}
  
  const char* GetOutputFile() const;

  MCalibrationChargeCam  &GetCalibrationCam()     { return fCalibrationCam; }  
  MCalibrationRelTimeCam &GetRelTimeCam()         { return fRelTimeCam;     }
  MCalibrationQECam      &GetQECam()              { return fQECam;          }    
  MBadPixelsCam          &GetBadPixels()          { return fBadPixels;      }

  Bool_t IsUseBlindPixel() const;
  Bool_t IsUsePINDiode()   const;
  
  void SetBadPixels(const MBadPixelsCam &bad)     { bad.Copy(fBadPixels);   }
  void SetExtractor(MExtractor* ext)              { fExtractor = ext; }
  void SetTimeExtractor(MExtractTime* ext)       { fTimeExtractor = ext; }
  void SetQECam    (const MCalibrationQECam &qe) { qe.Copy(fQECam);        }    
  void SetColor    (const MCalibrationCam::PulserColor_t color) { fColor = color; }

  void SetInput(MRunIter *iter) { fRuns=iter; }
  void SetOutputPath(const char *path=".");
  
  // Displays
  void SetFullDisplay()      { fDisplayType = kFullDisplay;      }
  void SetDataCheckDisplay() { fDisplayType = kDataCheckDisplay; }
  void SetNormalDisplay()    { fDisplayType = kNormalDisplay;    }

  // Rel. Time
  void SetRelTimeCalibration(const Bool_t b=kTRUE) { fRelTimes         = b; }

  // Data Check
  void SetDataCheck         (const Bool_t b=kTRUE) { fDataCheck        = b; SetDataCheckDisplay(); }

  // Debug
  void SetDebug             (const Bool_t b=kTRUE) { fDebug           = b; }
  
  // Devices
  void SetUseBlindPixel( const Bool_t b=kTRUE );
  void SetUsePINDiode  ( const Bool_t b=kTRUE );  
  
  Bool_t ReadCalibrationCam();
  Bool_t ProcessFile( MPedestalCam &pedcam );
  Bool_t Process    ( MPedestalCam &pedcam );
  
  ClassDef(MJCalibration, 0) // Tool to run a calibration per pulser colour and intensity
};

#endif
