#ifndef RecoLocalMuon_DTLinearDriftFromDBAlgo_H
#define RecoLocalMuon_DTLinearDriftFromDBAlgo_H

/** \class DTLinearDriftFromDBAlgo
 *  Concrete implementation of DTRecHitBaseAlgo.
 *  Compute drift distance using constant drift velocity
 *  read from database.
 *
 *  \author S.Bolognesi - INFN Torino
 */

#include "RecoLocalMuon/DTRecHit/interface/DTRecHitBaseAlgo.h"
#include "FWCore/Utilities/interface/ESGetToken.h"

class DTMtime;
class DTRecoConditions;
class MagneticField;
class DTMtimeRcd;
class DTRecoConditionsVdriftRcd;
class IdealMagneticFieldRecord;
class DTRecoConditionsUncertRcd;

class DTLinearDriftFromDBAlgo : public DTRecHitBaseAlgo {
public:
  /// Constructor
  DTLinearDriftFromDBAlgo(const edm::ParameterSet& config, edm::ConsumesCollector cc);

  /// Destructor
  ~DTLinearDriftFromDBAlgo() override;

  // Operations

  /// Pass the Event Setup to the algo at each event
  void setES(const edm::EventSetup& setup) override;

  /// First step in computation of Left/Right hits from a Digi.
  /// The results are the local position (in DTLayer frame) of the
  /// Left and Right hit, and the error (which is common). Returns
  /// false on failure. The hit is assumed to be at the wire center.
  bool compute(const DTLayer* layer,
               const DTDigi& digi,
               LocalPoint& leftPoint,
               LocalPoint& rightPoint,
               LocalError& error) const override;

  /// Second step in hit position computation.
  /// It is the same as first step since the angular information is not used
  /// NOTE: Only position and error of the new hit are modified
  bool compute(const DTLayer* layer,
               const DTRecHit1D& recHit1D,
               const float& angle,
               DTRecHit1D& newHit1D) const override;

  /// Third (and final) step in hits position computation.
  /// Also the hit position along the wire is available
  /// and can be used to correct the drift time for particle
  /// TOF and propagation of signal along the wire.
  /// NOTE: Only position and error of the new hit are modified
  bool compute(const DTLayer* layer,
               const DTRecHit1D& recHit1D,
               const float& angle,
               const GlobalPoint& globPos,
               DTRecHit1D& newHit1D) const override;

private:
  // Do the actual work.
  virtual bool compute(const DTLayer* layer,
                       const DTWireId& wireId,
                       const float digiTime,
                       const GlobalPoint& globPos,
                       LocalPoint& leftPoint,
                       LocalPoint& rightPoint,
                       LocalError& error,
                       int step) const;

  // Interface to the method which does the actual work suited for 2nd and 3rd steps
  virtual bool compute(const DTLayer* layer,
                       const DTWireId& wireId,
                       const float digiTime,
                       const GlobalPoint& globPos,
                       DTRecHit1D& newHit1D,
                       int step) const;

  // Map of meantimes (old DB format)
  const DTMtime* mTimeMap;
  edm::ESGetToken<DTMtime, DTMtimeRcd> mTimeMapToken_;

  // Drift velocity (new DB format)
  const DTRecoConditions* vDriftMap;
  edm::ESGetToken<DTRecoConditions, DTRecoConditionsVdriftRcd> vDriftMapToken_;

  // MF field
  const MagneticField* field;
  edm::ESGetToken<MagneticField, IdealMagneticFieldRecord> fieldToken_;
  int nominalB;

  // Map of hit uncertainties
  const DTRecoConditions* uncertMap;
  edm::ESGetToken<DTRecoConditions, DTRecoConditionsUncertRcd> uncertMapToken_;

  // Times below MinTime (ns) are considered as coming from previous BXs.
  const float minTime;

  // Times above MaxTime (ns) are considered as coming from following BXs
  const float maxTime;

  // Perform a correction to vDrift for the external wheels
  const bool doVdriftCorr;

  // Switch recalculating hit parameters from digi time in Step 2
  // (when off, Step 2 does nothing)
  const bool stepTwoFromDigi;

  // Assign hit uncertainties based on new uncertainties DB
  // If false, the value taken from vdrift DB is used instead.
  bool useUncertDB;

  // Read legacy format for vdrift and ttrig DBs
  bool readLegacyTTrigDB;
  bool readLegacyVDriftDB;

  // Switch on/off the verbosity
  const bool debug;
};
#endif  // RecoLocalMuon_DTLinearDriftFromDBAlgo_H
