#ifndef _mevt_Counter_h_
#define _mevt_Counter_h_

#include <evt/ComponentGroup.h>
#include <mevt/Module.h>
#include <mevt/CounterSimData.h>
#include <utl/ShadowPtr.h>
#include <utl/ConsecutiveEnumFactory.h>

// forward declaration used for friendship
namespace io {
  class Counter_ROOT;
}


namespace mevt {
  /**
   * \class Counter Counter.h "mevt/Counter.h"
   * \brief Counter level event data.
   *
   * \author Rodolfo Federico Gamarra
   * \date 08 Mar 2009
   * \ingroup mevt
   */

  class Counter {
    typedef evt::ComponentGroup<Module> InternalModuleCollection;
  public:
    /** 
     * \name Members for management of contained modules.
     */ 
    //@{
    typedef InternalModuleCollection::ComponentConstIterator ModuleConstIterator;
    typedef InternalModuleCollection::ComponentIterator      ModuleIterator;
    Module& GetModule(const int mId) {
      return fModules.Get(mId);
    }
    const Module& GetModule(const int mId) const {
      return fModules.Get(mId);
    }
    void MakeModule(const int mId) {
      fModules.Make(mId);
    }
    bool HasModule(const int mId) const {
      return fModules.Has(mId);
    }
    int GetNumberOfModules() const { 
      return fModules.GetNumberOf();
    }
    ModuleConstIterator ModulesBegin() const {
      return fModules.Begin();    
    }
    ModuleConstIterator ModulesEnd() const {
      return fModules.End();
    }
    ModuleIterator ModulesBegin() {
      return fModules.Begin();
    }
    ModuleIterator ModulesEnd() {
      return fModules.End();
    }
    //@} 
    /** 
     * \name Counter simulation data.
     */ 
    //@{
    CounterSimData& GetSimData() { 
      return *fSimData;
    }
    const CounterSimData& GetSimData() const { 
      return *fSimData;
    }
    void MakeSimData();
    bool HasSimData() const { 
      return fSimData;
    }
    //@}
    /** 
     * \brief Counter is flagged has having reconstructed data if
     * at least one of its associated modules has reconstructed data
     */ 
    // Counter reconstructed data 
    bool HasRecData() const;
    //@}
    /**
     * \brief The id of the counter.
     *
     * Among the existing classes (sevt, fevt) it seems
     * that the choice is not to couple them with the corresponding
     * det classes. So there's not method in them (evt classes) to 
     * retrieve the associated det one. This class and those
     * among its hierarchy stick to that; and so the correponding
     * singleton detector instance will have to be used in each
     * case.
     * Besides the circumlocution for retrieval, having the ids
     * exposed (and that's just not too good by itself) imposes
     * knowledge on the hierarchy structure from the client side,
     * given that the ids aren't unique but only inside the containing
     * parent within the hierarchy.
     */ 
    int GetId() const {
      return fId;
    }
    // Rely on implicit ones.
    //Counter(const Counter& counter);
    //Counter& operator=(const Counter& counter);

    //! \name Methods to check the counter status 
    //@{
     /**
     * \brief The muon counter status
     *
     * Setting the status of a counter is a tricky business since it may contain several modules, 
     * each in a different state. The possible counter states are candidate, silent or rejected. 
     * This is a sort of ordered hierarchy. A counter is:
     *  - candidate: has at least one candidate module 
     *  - silent: has at least a silent module (and no candidate modules)
     *  - rejected: has all modules rejected
     * The counter state is not stored or set in this class but derived from the status of its 
     * modules. The status therefore has to be set at module level.  
     */ 
    bool IsCandidate() const;
    /// Check if the counter is rejected
    bool IsRejected() const;
    /// Check if the counter is silent
    bool IsSilent() const;
    /// Check if the counter is "hardware" saturated (limit imposed by detector segmentation)
    bool IsSaturated() const;

    void SetT1( double t1){ fT1 = t1; } 
    double GetT1( ){ return fT1; } 
    /** 
     * \brief The number of estimated muons of the counter is calculated 
     * as the sum of the estimated muons of the associated modules
     * This function returns -1 if any of the counter modules is
     * saturated 
     */ 
    double GetNumberOfEstimatedMuons() const;
    double GetNumberOfMuonsErrorHigh() const;
    double GetNumberOfMuonsErrorLow() const;

    /**
    * \brief The lower limit to the number of muons in a counter
    *
    * The low limit of muons provides a valid option to the minimum bound to muons
    * specially useful for saturated counters, where the number of muons and therefore
    * the error bars size are infinite. The limit is calculated as the sum module limits.
    *
    */ 
    double GetNumberOfMuonsLowLimit() const; 

    double GetActiveArea() const;
    /** 
     * \brief The density measured by a counter is the calculated
     * as the number of estimated muons over the active area.
     * This function returns -1 if any of the counter modules is
     * saturated 
     */ 
    double GetMuonDensity() const;
    double GetMuonDensityErrorHigh() const;
    double GetMuonDensityErrorLow() const;

    /** 
     * \brief The number of windows with a signal of the counter is calculated 
     * as the sum of the windows with a signal of the associated modules
     * Modules with data are included, including saturated ones. 
     */ 
    unsigned int GetNumberOfChannelsOn() const;
    /** 
     * \brief The LDF residual of the counter is calculated 
     * as the sum of the estimated muons of the associated modules
     * Modules with data & unsaturated are included only 
     */ 
    double GetLDFResidual() const; 

    // Implicit ones.
    //Counter(const Counter& counter);
    //Counter& operator=(const Counter& counter);
  private:

    Counter();
    ~Counter();
    /**
     * \brief Constructs the Counter with the given identificator.
     */ 
    Counter(int cId) : fId(cId) { }
    /**
     * \brief Friendship to allow creation.
     *
     */ 
    friend class evt::ComponentGroup<Counter>;
    /**
     * \brief Friendship for destruction.
     *
     * Depends on evt::ComponentGroup innards.
     */ 
    template<class T>
    friend void boost::checked_delete(T*);
    /* 
     * XXX Up to now, no refactor on Sim + Rec + id pattern for evt classes;
     * keep the current usage: there could be a superclass for rec, sim,
     * calib: but that seems too much and not worth (would lead to multiple
     * virtual inhertance).
     * Another posibility is to define a 
     * a wrapper (to ShadowPtr) in order
     * to put there this logic (make/has/get) for single values, but that
     * would be the only logic but there.
     */

    /**
     * \brief Count the number of modules in the counter by status
     *
     */ 
    size_t CountCandidateModules() const;
    size_t CountSilentModules() const;
    size_t CountRejectedModules() const;

    int fId;
    double fT1;
    InternalModuleCollection fModules;
    utl::ShadowPtr<CounterSimData> fSimData;
//    utl::ShadowPtr<CounterRecData> fRecData;
  };

} // namespace mevt

#endif