#ifndef TkDetLayers_TIDRing_h
#define TkDetLayers_TIDRing_h

#include "TrackingTools/DetLayers/interface/GeometricSearchDet.h"
#include "Utilities/BinningTools/interface/PeriodicBinFinderInPhi.h"
#include "SubLayerCrossings.h"
#include "DataFormats/GeometrySurface/interface/BoundDisk.h"

/** A concrete implementation for TID rings 
 */

#pragma GCC visibility push(hidden)
class TIDRing final : public GeometricSearchDet {
public:
  TIDRing(std::vector<const GeomDet*>& innerDets, std::vector<const GeomDet*>& outerDets);
  ~TIDRing() override;

  // GeometricSearchDet interface
  const BoundSurface& surface() const override { return *theDisk; }

  const std::vector<const GeomDet*>& basicComponents() const override { return theDets; }

  const std::vector<const GeometricSearchDet*>& components() const override __attribute__((cold));

  std::pair<bool, TrajectoryStateOnSurface> compatible(const TrajectoryStateOnSurface&,
                                                       const Propagator&,
                                                       const MeasurementEstimator&) const override;

  void groupedCompatibleDetsV(const TrajectoryStateOnSurface& tsos,
                              const Propagator& prop,
                              const MeasurementEstimator& est,
                              std::vector<DetGroup>& result) const override __attribute__((hot));

  //Extension of interface
  virtual const BoundDisk& specificSurface() const { return *theDisk; }

private:
  // private methods for the implementation of groupedCompatibleDets()

  SubLayerCrossings computeCrossings(const TrajectoryStateOnSurface& tsos, PropagationDirection propDir) const
      __attribute__((hot));

  bool addClosest(const TrajectoryStateOnSurface& tsos,
                  const Propagator& prop,
                  const MeasurementEstimator& est,
                  const SubLayerCrossing& crossing,
                  std::vector<DetGroup>& result) const __attribute__((hot));

  void searchNeighbors(const TrajectoryStateOnSurface& tsos,
                       const Propagator& prop,
                       const MeasurementEstimator& est,
                       const SubLayerCrossing& crossing,
                       float window,
                       std::vector<DetGroup>& result,
                       bool checkClosest) const __attribute__((hot));

  const std::vector<const GeomDet*>& subLayer(int ind) const { return (ind == 0 ? theFrontDets : theBackDets); }

private:
  std::vector<const GeomDet*> theDets;
  std::vector<const GeomDet*> theFrontDets;
  std::vector<const GeomDet*> theBackDets;

  ReferenceCountingPointer<BoundDisk> theDisk;
  ReferenceCountingPointer<BoundDisk> theFrontDisk;
  ReferenceCountingPointer<BoundDisk> theBackDisk;

  typedef PeriodicBinFinderInPhi<float> BinFinderType;

  BinFinderType theFrontBinFinder;
  BinFinderType theBackBinFinder;
};

#pragma GCC visibility pop
#endif
