////////////////////////////////////////////////////////////////////////
/// \class RAT::DQPMTProc
///
/// \brief   Data quality PMT processor
///
/// \author Ashley R. Back <a.r.back@qmul.ac.uk>
///
/// REVISION HISTORY:\n
///   2014-11-28 : a.r.back@qmul.ac.uk - Tidied up for FTB processing
///   2016-04-24 : Mark Stringer ms711@sussex.ac.uk - Added CHS check for coverage
/// \details Checks calibration status of each PMT for each event.\n
/// Then runs several checks of coverage provided by fully calibrated\n
/// "usable" PMTs.
///
////////////////////////////////////////////////////////////////////////

#ifndef __RAT_DQPMTProc__
#define __RAT_DQPMTProc__

#include <RAT/Processor.hh>
#include <RAT/DataQualityProc.hh>
#include <RAT/DB.hh>
#include <RAT/DBLink.hh>
#include <RAT/DU/ChanHWStatus.hh>

#include <vector>
#include <map>

class TFile;
class TH2D;
class TGraph;

namespace RAT
{
  namespace DS
  {
    class Run;
    class Entry;
    class EV;
  }
  namespace DU
  {
    class PMTInfo;
  }
}

namespace RAT
{

  class DQPMTProc : public DataQualityProc
  {
  public:

    DQPMTProc();

    virtual ~DQPMTProc();

    virtual void BeginOfRun( DS::Run& run );

    struct PanelProp
    {
      int type;
      int coverageThresh;
      int coverageCount;
    };

    /// Returns area of a cap on a sphere. For use in coverage check 4, not yet implemented.
    virtual double GetCapArea( const double r, const double a ) const;

    virtual Processor::Result DSEvent( DS::Run& run, DS::Entry& ds );

    /// Fill TH2D coverage map
    virtual void FillCrateCoverageMap( const int lcn, TH2D* h1 ) const;

    /// Fill TH1D coverage map
    virtual void FillCrateCoverageMap( const int lcn, TH1D* h1 ) const;

    /// Increments coverage counters
    virtual void UpdateCoverage( const int lcn, const DU::PMTInfo& fPMTInfo );

    virtual void EndOfRun( DS::Run& run );

    /// Checks coverage counters against coverage check criteria
    virtual void RunCoverageChecks();

  protected:
    virtual Processor::Result Event( DS::Entry& ds, DS::EV& ev );

    DBLinkPtr fGeoPsup; ///<link to RATDB "GEO" table, index "psup"
    double fNeckRadius;
    double fPsupRadius;
    DBLinkPtr fPanelInfo; ///<link to RATDB "PANELINFO" table
    std::vector<int> fPanelNumbers; ///<vector to hold panel numbers from "PANELINFO", size=total panels, ordering=none (as in PANELINFO)
    unsigned int fPanelCount;
    std::vector<int> fPanelTypes; ///<vector to hold panel types from "PANELINFO", size=total panels, ordering=as fPanelNumbers

    unsigned int fChannelCount;

    DBLinkPtr fDQChecks; ///<link to RATDB "DQCHECKS" table
    double fGeneralCoverage;
    double fGeneralCovThresh;

    unsigned int fCrateCount;
    std::vector<double> fCrateCoverage; ///<vector to hold crate occupancy counters, size=total crates, ordering=crate number
    double fInCrateCovThresh;
    double fCrateCovThresh;
    double fPanelCovThresh;

    std::vector<int> fPMTCalStatuses; ///<vector to hold PMT calibration statuses, size=total channels, ordering=lcn

    std::map<int, PanelProp> fPanels; ///<map to hold panel data, size=total panels, no ordering, key=panel number, value=panel properties
    PanelProp fPanelProperties; ///<structure to store panel properties

    unsigned int fNormalCount;
    unsigned int fOWLCount;
    unsigned int fLGCount;
    unsigned int fCalibCount;
    unsigned int fSpareCount;
    unsigned int fButtCount;
    unsigned int fNeckCount;
    unsigned int fFECDCount;

    double fNormalPMTsArea; ///<area inside psup containing normal PMTs only
    double fCapCount; ///<PMTs that would be contained in area the size of neck opening
    double fNeckAreaCovThresh; ///<threshold for coverage check 4 - not yet implemented

    std::vector<double> fNeckAreaCoverage; ///<unused vector for holding counters for coverage check 4

    TFile* fRootFile; ///<root file to hold output histograms and TGraphs
    TH1D* fUncalPMTs;
    TH1D* fcalPMTs;
    TH2D* fCrateOccupancyMap; ///<crate occupancy, calibrated PMTs
    TH2D* fUnCalCrateOccupancyMap; ///<crate occupancy, uncalibrated PMTs
    TGraph* fGeoCoverageMap; ///<phi vs theta scatter plot, calibrated PMTs

    std::vector<double> fPMTPhi; ///<vector, phi coordinates for calibrated PMTs, size=total calibrated PMTs, ordering=as fPMTCalStatuses (calibrated only)
    std::vector<double> fPMTTheta; ///<vector, theta coordinates for calibrated PMTs, size=total calibrated PMTs, ordering=as fPMTTheta
  private:
    DU::PMTInfo fPMTInfo;
    DU::ChanHWStatus fCHS;
    TH2D CrateMapFromChannelHisto(TH1D);
    int crateNumber(int LCN);
    int cardNumber(int LCN);
    int channelNumber(int LCN);
  };

} // namespace RAT

#endif // DQPMTProc