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

// STAR
#include "StMuDSTMaker/COMMON/StMuTrack.h"
#include "StEmcUtil/geometry/StEmcGeom.h"
#include "StEvent/StTrackGeometry.h"
// Local
#include "Track.h"

ClassImp(Track);

Track::Track()
{
  mId = 0;
  mFlag = 0;
  mCharge = 0;
  mNumberOfHits = 0;
  mdEdx = 0;
  mEmcHits.Clear();
  mEmcCluster = 0;
  mSmdEtaCluster = 0;
  mSmdPhiCluster = 0;
  mCtbHit = 0;
  mEvent = 0;
}

Track::Track(StMuTrack* track)
//Track::Track(StMuTrack* track,Event* event)//changed for Mult Vz study
{
  mId = track->id();
  mFlag = track->flag();
  mCharge = track->charge();
  mNumberOfHits = track->nHitsFit();
  mdEdx = track->dEdx() / keV;
  //mMomentum = track->helix().momentumAt(track->helix().pathLength(0,0),(event->magneticField())/10.).xyz();//ddas
  mMomentum = track->momentum().xyz();
  mDca = track->dcaGlobal().xyz();
  mHelix = track->helix();
  mOuterHelix = track->outerHelix();
  mEmcHits.Clear();
  mEmcCluster = 0;
  mSmdEtaCluster = 0;
  mSmdPhiCluster = 0;
  mCtbHit = 0;
  mEvent = 0;
}

Track::Track(const Track& track)
{
  mId = track.mId;
  mFlag = track.mFlag;
  mCharge = track.mCharge;
  mNumberOfHits = track.mNumberOfHits;
  mdEdx = track.mdEdx;
  mMomentum = track.mMomentum;
  mDca = track.mDca;
  mHelix = track.mHelix;
  mOuterHelix = track.mOuterHelix;
  mEmcHits.Clear();
  mEmcCluster = 0;
  mSmdEtaCluster = 0;
  mSmdPhiCluster = 0;
  mCtbHit = 0;
  mEvent = track.mEvent;
}

TVector3 Track::distanceToEmcHit(EmcHit* hit) const throw(Exception)
{
  double radius = hit->position().Perp();
  return positionAtRadius(radius) - hit->position();
}

TVector3 Track::distanceToEmcCluster() const throw(Exception)
{
  EmcCluster* cluster = emcCluster();
  if (!cluster) throw Exception();
  double radius = cluster->position().Perp();
  return positionAtRadius(radius) - cluster->position();
}

TVector3 Track::positionAtRadius(double radius) const throw(Exception)
{
  static const pair<double, double> VALUE(999999999., 999999999.); // No solution

  if (mOuterHelix.origin().perp() > radius) throw Exception();
  pair<double, double> ss = mOuterHelix.pathLength(radius);
  if (!finite(ss.first) || !finite(ss.second)) throw Exception();
  if (ss == VALUE) throw Exception();

  double s = 0;

  if (ss.first > 0 && ss.second > 0)
    s = ss.first;
  else if (ss.first >= 0 && ss.second < 0)
    s = ss.first;
  else if (ss.first < 0 && ss.second >= 0)
    s = ss.second;
  else
    throw Exception();

  return mOuterHelix.at(s).xyz();
}

float Track::sumTrackPt(float radius) const
{
  float sum = 0;
  TIter next(&event()->tracks());
  while (Track* track = (Track*)next()) {
    if (track->id() != id()) {
      float deta = track->eta() - eta();
      float dphi = TVector2::Phi_mpi_pi(track->phi() - phi());
      if (hypot(deta, dphi) < radius) sum += track->pt();
    }
  }
  return sum;
}

float Track::sumTowerPt(float radius) const
{
  float sum = 0;
  TIter next(&event()->emcHits());
  while (EmcHit* hit = (EmcHit*)next()) {
    float deta = hit->position().Eta() - eta();
    float dphi = TVector2::Phi_mpi_pi(hit->position().Phi() - phi());
    if (hypot(deta, dphi) < radius) sum += hit->pt();
  }
  return sum;
}
