///////////////////////////////////////////////////////////////////////
//
// Collection of hit PMTs for the current event. Is a singleton. Each
// PMT hit is registered in this class. The collection is cleared at the
// start of each event. The DQXX information is applied here.
//
// Author: Phil G Jones <p.g.jones@qmul.ac.uk>
//
// REVISION HISTORY:
//     2013-12-16 : P G Jones - New file, replaces GLG4HitPMTCollection.
//
///////////////////////////////////////////////////////////////////////

#ifndef __RAT_HitPMTCollection_hh__
#define __RAT_HitPMTCollection_hh__

#include <map>
#include <vector>

namespace RAT
{

namespace DS
{
  class MCPMT;
  class MCPE;
} // ::DS

class HitPMTCollection
{
public:
  // Singleton class instance
  //
  // Returns a pointer to the HitPMTCollection
  inline static HitPMTCollection* Get();

  // Destroy the collection
  virtual ~HitPMTCollection();

  // Initialise the collection for a new run
  void BeginOfRun();

  // Initialise the collection for a new event
  void BeginOfEvent();

  // A new photoelectron has been created
  //
  // pmtID: the PMT that has been hit
  // photoElectron: the photoelectron to consider
  void DetectPhotoelectron( const unsigned int pmtID,
                            DS::MCPE& photoElectron );

  // Returns the pmt collection, ensuring it has been sorted by time ascending
  //
  // Returns a constant reference to the pmt collection
  const std::vector<DS::MCPMT*>& GetSortedPMTCollection();
private:
  // Sort the pmt collection by time ascending
  void Sort();

  std::vector<DS::MCPMT*> fMCPMTs; // The MCPMT collection
  std::map<unsigned int, DS::MCPMT*> fMCPMTMap; // The MCPMT collection, mapped by pmt ID
  bool fSorted; // Is the collection sorted?

  std::map<unsigned int, unsigned int> fNormalToLowGain; // Map between normal PMTs (which are geo-built) and low gain (which are not)

  double fEventCutOffTime; // Max time photoelectrons can have to be included in collection

  // Prevent usage of methods below
  HitPMTCollection() { }
  HitPMTCollection( HitPMTCollection& );
  void operator=( HitPMTCollection& );
};

inline HitPMTCollection*
HitPMTCollection::Get()
{
  static HitPMTCollection hitPMTCollection;
  return &hitPMTCollection;
}

} //::RAT

#endif