// -*- mode: C++ -*-

//
// Pibero Djawotho <pibero@indiana.edu>
// Indiana University
// 30 July 2007
//

#ifndef TRACK_H
#define TRACK_H

// STAR
class StMuTrack;

// ROOT
#include "TObject.h"
#include "TVector3.h"
#include "TRef.h"
#include "TRefArray.h"

// STAR
#include "StPhysicalHelix.hh"

// Local
#include "EmcHit.h"
#include "EmcCluster.h"
#include "SmdCluster.h"
#include "CtbHit.h"
#include "Event.h"

class Track : public TObject {
public:
  class Exception {};

  Track();
  Track(StMuTrack* track);
  //Track(StMuTrack* track,Event* event);//this was done to check vertices
  Track(const Track& track);
  ~Track() {}

  int id() const;
  int flag() const;
  int charge() const;
  int numberOfHits() const;
  float dEdx() const;
  TVector3& momentum();
  float pz() const;
  float pt() const;
  float eta() const;
  float phi() const;
  TVector3& dca(); // Distance of closest approach from vertex
  StPhysicalHelix& helix(); // Returns inner helix (first measured point)
  StPhysicalHelix& outerHelix(); // Returns outer helix (last measured point)

  TRefArray& emcHits();
  EmcCluster* emcCluster() const;
  SmdCluster* smdEtaCluster() const;
  SmdCluster* smdPhiCluster() const;
  CtbHit* ctbHit() const;
  Event* event() const;

  TVector3 distanceToEmcHit(EmcHit* hit) const throw(Exception);
  TVector3 distanceToOuterEmcHit() const throw(Exception);
  TVector3 distanceToEmcCluster() const throw(Exception);
  TVector3 distanceToSmdEtaCluster() const throw(Exception);
  TVector3 distanceToSmdPhiCluster() const throw(Exception);
  TVector3 positionAtRadius(double radius) const throw(Exception);

  float sumPt(float radius) const;
  float sumTrackPt(float radius) const;
  float sumTowerPt(float radius) const;

  void setEmcCluster(EmcCluster* cluster);
  void setSmdEtaCluster(SmdCluster* cluster);
  void setSmdPhiCluster(SmdCluster* cluster);
  void setCtbHit(CtbHit* hit);
  void setEvent(Event* event);

private:
  int mId;
  int mFlag;
  int mCharge;
  int mNumberOfHits;
  float mdEdx;
  TVector3 mMomentum;
  TVector3 mDca;
  StPhysicalHelix mHelix;
  StPhysicalHelix mOuterHelix;
  TRefArray mEmcHits;
  TRef mEmcCluster;
  TRef mSmdEtaCluster;
  TRef mSmdPhiCluster;
  TRef mCtbHit;
  TRef mEvent;

  ClassDef(Track, 1);
};

inline int Track::id() const { return mId; }
inline int Track::charge() const { return mCharge; }
inline int Track::numberOfHits() const { return mNumberOfHits; }
inline float Track::dEdx() const { return mdEdx; }
inline TVector3& Track::momentum() { return mMomentum; }
inline float Track::pz() const { return mMomentum.Pz(); }
inline float Track::pt() const { return mMomentum.Pt(); }
inline float Track::eta() const { return mMomentum.Eta(); }
inline float Track::phi() const { return mMomentum.Phi(); }
inline TVector3& Track::dca() { return mDca; }
inline StPhysicalHelix& Track::helix() { return mHelix; }
inline StPhysicalHelix& Track::outerHelix() { return mOuterHelix; }
inline TRefArray& Track::emcHits() { return mEmcHits; }
inline EmcCluster* Track::emcCluster() const { return (EmcCluster*)mEmcCluster.GetObject(); }
inline SmdCluster* Track::smdEtaCluster() const { return (SmdCluster*)mSmdEtaCluster.GetObject(); }
inline SmdCluster* Track::smdPhiCluster() const { return (SmdCluster*)mSmdPhiCluster.GetObject(); }
inline CtbHit* Track::ctbHit() const { return (CtbHit*)mCtbHit.GetObject(); }
inline Event* Track::event() const { return (Event*)mEvent.GetObject(); }

inline float Track::sumPt(float radius) const { return sumTrackPt(radius) + sumTowerPt(radius); }

inline void Track::setEmcCluster(EmcCluster* cluster) { mEmcCluster = cluster; }
inline void Track::setSmdEtaCluster(SmdCluster* cluster) { mSmdEtaCluster = cluster; }
inline void Track::setSmdPhiCluster(SmdCluster* cluster) { mSmdPhiCluster = cluster; }
inline void Track::setCtbHit(CtbHit* hit) { mCtbHit = hit; }
inline void Track::setEvent(Event* event) { mEvent = event; }

#endif
