////////////////////////////////////////////////////////////////////////
/// \class RAT::PartialWaterFitter
///
/// \brief Fitter for partial fill (e.g. float-the-boat running)
///
/// \author M Mottram <m.mottram@qmul.ac.uk>
///
/// REVISION HISTORY:\n
///     - 2014-11-28 : M Mottram - first instance.
///
/// \details Based entirely on the default WaterFitter with some
///          minor adjustments (e.g. to the PMT selectors and the
///          direction reconstruction method).
///
////////////////////////////////////////////////////////////////////////

#ifndef __RAT_PartialWaterFitter__
#define __RAT_PartialWaterFitter__

#include <RAT/Processor.hh>

namespace RAT
{
namespace DS
{
  class EV;
}
namespace Methods
{
  class Method;
}
namespace PDFs
{
  class PDF;
}
namespace Optimisers
{
  class Optimiser;
}
namespace PMTSelectors
{
  class PMTSelector;
}
namespace Classifiers
{
  class Classifier;
}
namespace DS{
  class FitResult;
}

class PartialWaterFitter : public Processor
{
public:
  PartialWaterFitter();
  virtual ~PartialWaterFitter();

  /// Called at the beginning of runs to setup the waterFitter
  ///
  /// @param[in] run
  void BeginOfRun( DS::Run& run );

  /// Called to invoke the waterFitter
  ///
  /// @param[in, out] run Data structure for the event
  /// @param[in, out] ds Data structure for the event
  virtual Processor::Result DSEvent( DS::Run& run, DS::Entry& ds );

  /// Called at the end of runs
  ///
  /// @param[in] run
  void EndOfRun( DS::Run& run );

  /// Ability to set the zCut parameters
  ///
  /// @param[in] param name
  /// @param[in] value
  void SetD( const std::string& param, double value );

protected:

  virtual Processor::Result Event( DS::Run& run, DS::EV& ev );

  /// Set the final result from the default fit routine and return OKTRUE status
  ///
  /// @param[in] waterResult result from the default fit routine
  /// @param[in] ev DS::EV
  /// @param[in] currentPass pass number from the Meta information
  /// @returns Processor OKTRUE if passed
  Processor::Result SetResult( DS::FitResult& waterResult, DS::EV& ev, size_t currentPass);

  Methods::Method* fQuadSeed; ///< seed for position fit and meta-optimisers
  Methods::Method* fDirectionSeed; ///< seed for direction fit and meta-optimisers

  Methods::Method*  fPositionTime; ///< main position method
  Optimisers::Optimiser* fMetaDrivePowell; ///< meta-optimiser for position fit
  PMTSelectors::PMTSelector* fZCut; ///< pmt selector for position fit
  PDFs::PDF* fGV1D; ///< pdf for position fit

  Methods::Method*  fDirection; ///< main direction method
  PMTSelectors::PMTSelector* fModeCut; ///< pmt selector for direction fit
  Optimisers::Optimiser* fMetaDirection; ///< meta-optimiser for direction fit
  PDFs::PDF* fDirectionPDF; ///< pdf for direction fit

  Methods::Method* fEnergyLookup; ///< main energy method

  Classifiers::Classifier* fBeta14; ///< beta14 isotropy classifier
  Classifiers::Classifier* fITR; ///< in time ratio classifier
  Classifiers::Classifier* fQPDT; ///< qpdt classifier

  size_t fCutOff; ///< Lower limit to which the quad method is an acceptable seed
};

} // ::RAT

#endif