////////////////////////////////////////////////////////////////////////
// RAT::PMTSelectors::TimeResidualCut
//
// Selects PMTs based on their hit time residual.
//
// Matt Mottram <m.mottram@qmul.ac.uk> --contact person
//
// REVISION HISTORY:
//    - 2014/10/27: M. Mottram: new file.
//    - 2015/02/24: E. Beier: Make default time residual cut the
//      values in the macro. If no values in macro, uses the values
//      in SELECTOR_ISOTROPY.ratdb. If there is no entry in ratdb
//      file, defaults to +/-99999.
//    - 2016/08/30: M. Mottram: added option to use refracted light path
//    - 2017/09/25: W Heintzelman:  added GetLowCut and GetHighCut functions
//                        move transit time calculation to separate function
//    - 2020/09/01: Logan Lebanowski - Properly account for partial fill
//
// May only be used where a FitResult with position information
// is available.  Options available to set low and high time cuts.
//
////////////////////////////////////////////////////////////////////////

#ifndef __RAT_PMTSelector_TimeResidualCut__
#define __RAT_PMTSelector_TimeResidualCut__

#include <RAT/PMTSelector.hh>
#include <RAT/DU/TimeResidualCalculator.hh>

namespace RAT
{

  namespace PMTSelectors
  {

    class TimeResidualCut : public PMTSelector
    {
    public:
      /// Return the Name
      std::string
      GetName() const { return Name(); };

      double GetLowCut()  { return fLowCut; }
      double GetHighCut() { return fHighCut; }

      /// Fitter structure name
      static std::string
      Name() { return std::string( "timeResidualCut" ); }

      /// Initialise the selector
      void Initialise( const std::string& );

      /// Function called at the start of run
      void BeginOfRun( DS::Run& ) ;

      /// Function called at the end of run; unused here
      void EndOfRun( DS::Run& ) { };

      /// Set parameter values
      ///
      /// @param[in] param string name of the parameter
      /// @param[in] value to set
      void SetD( const std::string& param, double value );

      /// Set parameter values
      ///
      /// @param[in] param string name of the parameter
      /// @param[in] value to set
      void SetI( const std::string& param, int value );

      /// Calculate transit time
      double CalcTransitTime( const TVector3& fitPosition, const TVector3& pmtPosition);

      /// Main Selector function
      ///
      /// @param[in] data PMT data for fitters
      /// @param[in] vertex fit vertex information to select by
      std::vector<FitterPMT>
      GetSelectedPMTs( const std::vector<FitterPMT>& data,
                       const DS::FitVertex& vertex );

    protected:
      bool fUseGroup;  ///< Use group (true) or effective (false) velocity; defaults to false
      bool fUseRefracted; ///< Use the refracted light path
      double fLowCut;  ///< Low time cut relative to time residual of 0 (ns)
      double fHighCut; ///< High time cut relative to time residual of 0 (ns)
      DU::TimeResidualCalculator fTRCalc; ///< Time residual calculator for a given run
      size_t fPSUPSystemId; // coordinate system id for Point3D
    };

  } //::PMTSelector

} //::RAT

#endif