//_____________________________________________________________________________
///
/// \class TrackContext
///
/// TrackContext - encapsulates CandTrack context for the fitter.
///
/// \author Sergei avva@fnal.gov
///

#include <cassert>

#include "DataUtil/CDL2STL.h"


#include "Candidate/CandContext.h"
#include "Plex/PlexPlaneId.h"
#include "RecoBase/CandStripHandle.h"
#include "RecoBase/CandFitTrackHandle.h"
#include "Validity/VldContext.h"

#include "CandFitTrackSA/ConstFT.h"
#include "CandFitTrackSA/TracerSA.h"
#include "CandFitTrackSA/TrackContext.h"

#include "Strip.h"

using namespace ConstFT;
///
/// default ctor
///
// TrackContext::TrackContext() :
//     fCandTrackHandle(0), fVldc(), 
//     fBegPlaneId(), fEndPlaneId(),  
//     fDir(0), fPrange(0.)
// {
//     TracerSA trace("TrackContext::TrackContext()");
// }

///
/// ctor
///
TrackContext::TrackContext(CandContext& trackCandContext) :
    fCandTrackHandle(0), fVldc(), 
    fBegPlaneId(), fEndPlaneId(),  
    fDir(0), fPrange(0.),
    fStrips()
{
    TracerSA trace("TrackContext::TrackContext(CandContext&)");
    
    fCandTrackHandle = dynamic_cast<const CandTrackHandle*> 
                                                (trackCandContext.GetDataIn());
    assert(fCandTrackHandle && 
            "CandContext is either NULL or not castable to CandTrackHandle!");
    
    fVldc = *fCandTrackHandle->GetVldContext();
    
    fBegPlaneId = PlexPlaneId(fVldc.GetDetector(), 
                                fCandTrackHandle->GetBegPlane());
    fEndPlaneId = PlexPlaneId(fVldc.GetDetector(), 
                                fCandTrackHandle->GetEndPlane());

    fDir = fEndPlaneId > fBegPlaneId ? 1 : -1;    

    Float_t range = fCandTrackHandle->GetRange();
    
    // need to ask Alysia where the real range->prange
    // conersion function lives and call it here instead
    // of doing copy/paste
    fPrange = 0.048 + 1.660e-3*range + 3.057e-8*range*range;

    FillTrackStrips();
}

///
/// dtor
///
TrackContext::~TrackContext()
{
    TracerSA trace("TrackContext::~TrackContext()");
}


///
///
///
void      TrackContext::FillTrackStrips()
{
    typedef const CandStripHandle CSH;
    typedef CSH* CSHPtr;
    typedef std::vector<CSHPtr>::iterator CSHItr;

    TracerSA trace("TrackContext::FillTrackStrips()");
    // convert daughter list to STL vector
    std::vector<CSHPtr> stripList(DataUtil::CDL2STLvector<CSH>(*fCandTrackHandle));
    for (CSHItr it = stripList.begin(); it != stripList.end(); ++it) {
        fStrips.push_back(
              Reco::Strip_t(
                  new Reco::Strip(  (*it)->GetStrip(),
                                    (*it)->GetPlane(),
                                    (*it)->GetDemuxVetoFlag(),
                                    (*it)->GetPlaneView(),
                                    (*it)->GetTPos(),
                                    (*it)->GetZPos(),
                                    (*it)->GetCharge(),
                                    (*it)->GetStripEndId()
                                  )
                            )
                );
    }
}

///
///
///
Int_t TrackContext::GetNTrackPlaneU() const
{
    TracerSA trace("TrackContext::GetNTrackPlaneU()");
    return fCandTrackHandle->GetNTrackPlane(PlaneView::kU);
}


///
///
///
Int_t TrackContext::GetNTrackPlaneV() const
{
    TracerSA trace("TrackContext::GetNTrackPlaneV()");
    return fCandTrackHandle->GetNTrackPlane(PlaneView::kV);
}


///
///
///
Int_t TrackContext::GetNTrackPlane() const
{
    TracerSA trace("TrackContext::GetNTrackPlane()");    
    return fCandTrackHandle->GetNTrackPlane(PlaneView::kUnknown);
}


///
///
///
Int_t       TrackContext::GetPassSR() const
{
    const CandFitTrackHandle* pcfth =
        dynamic_cast<const CandFitTrackHandle*> (fCandTrackHandle);
    
    if ( pcfth ) {
        return pcfth->GetPass();
    }
    
    return 0;
}


///
///
///    
Double_t    TrackContext::GetQPSR() const
{
    const CandFitTrackHandle* pcfth =
        dynamic_cast<const CandFitTrackHandle*> (fCandTrackHandle);
    
    if ( pcfth ) {
        Double_t p  = pcfth->GetMomentumCurve();
        Int_t    q  = static_cast<Int_t> (pcfth->GetEMCharge());
        
        if ( TMath::Abs(p) > TinyNumber ) {
            return q/p;
        } else {
            return -5.;
        }
    }
    
    return -5.0;
}
    

///
///
///
Double_t    TrackContext::GetEQPSR() const
{
    const CandFitTrackHandle* pcfth =
        dynamic_cast<const CandFitTrackHandle*> (fCandTrackHandle);
    
    if ( pcfth ) {
        return pcfth->GetVtxQPError();
    }
    
    return 0.0;
}


///
///
///
Double_t    TrackContext::GetChi2SR() const
{
    const CandFitTrackHandle* pcfth =
        dynamic_cast<const CandFitTrackHandle*> (fCandTrackHandle);
    
    if ( pcfth ) {
        return pcfth->GetChi2();
    }
    
    return 0.0;
}


///
///
///
Double_t    TrackContext::GetRChi2SR() const
{
    const CandFitTrackHandle* pcfth =
        dynamic_cast<const CandFitTrackHandle*> (fCandTrackHandle);
    
    if ( pcfth ) {
        Double_t chi2 = pcfth->GetChi2();
        Int_t    ndf  = pcfth->GetNDOF();
        
        if ( TMath::Abs(ndf) > TinyNumber ) {
            return chi2/ndf;
        } else {
            return -1.;
        }
    }
    return -1.0;
}


///
///
///
Double_t    TrackContext::GetCpuSR() const
{
    const CandFitTrackHandle* pcfth =
        dynamic_cast<const CandFitTrackHandle*> (fCandTrackHandle);
    
    if ( pcfth ) {
        return pcfth->GetCPUTime();
    }
    
    return 0.0;
}


///
///
///
Double_t    TrackContext::GetUSR() const
{
    const CandFitTrackHandle* pcfth =
        dynamic_cast<const CandFitTrackHandle*> (fCandTrackHandle);
    
    if ( pcfth ) {
        return pcfth->GetVtxU();
    }
    
    return 0.0;
}


///
///
///
Double_t    TrackContext::GetUErrorSR() const
{
    const CandFitTrackHandle* pcfth =
        dynamic_cast<const CandFitTrackHandle*> (fCandTrackHandle);
    
    if ( pcfth ) {
        return pcfth->GetVtxUError();
    }
    
    return 0.0;
}


///
///
///
Double_t    TrackContext::GetVSR() const
{
    const CandFitTrackHandle* pcfth =
        dynamic_cast<const CandFitTrackHandle*> (fCandTrackHandle);
    
    if ( pcfth ) {
        return pcfth->GetVtxV();
    }
    
    return 0.0;
}


///
///
///
Double_t    TrackContext::GetVErrorSR() const
{
    const CandFitTrackHandle* pcfth =
        dynamic_cast<const CandFitTrackHandle*> (fCandTrackHandle);
    
    if ( pcfth ) {
        return pcfth->GetVtxVError();
    }
    
    return 0.0;
}


///
///
///
Double_t    TrackContext::GetDirCosUSR() const
{
    const CandFitTrackHandle* pcfth =
        dynamic_cast<const CandFitTrackHandle*> (fCandTrackHandle);
    
    if ( pcfth ) {
        return pcfth->GetVtxDirCosU();
    }
    
    return 0.0;
}


///
///
///
Double_t    TrackContext::GetEDirCosUSR() const
{
    const CandFitTrackHandle* pcfth =
        dynamic_cast<const CandFitTrackHandle*> (fCandTrackHandle);
    
    if ( pcfth ) {
        return pcfth->GetVtxdUError();
    }
    
    return 0.0;
}


///
///
///
Double_t    TrackContext::GetDirCosVSR() const
{
    const CandFitTrackHandle* pcfth =
        dynamic_cast<const CandFitTrackHandle*> (fCandTrackHandle);
    
    if ( pcfth ) {
        return pcfth->GetVtxDirCosV();
    }
    
    return 0.0;
}


///
///
///
Double_t    TrackContext::GetEDirCosVSR() const
{
    const CandFitTrackHandle* pcfth =
        dynamic_cast<const CandFitTrackHandle*> (fCandTrackHandle);
    
    if ( pcfth ) {
        return pcfth->GetVtxdVError();
    }
    
    return 0.0;
}


///
///
///
Double_t    TrackContext::GetDirCosZSR() const
{
    const CandFitTrackHandle* pcfth =
        dynamic_cast<const CandFitTrackHandle*> (fCandTrackHandle);
    
    if ( pcfth ) {
        return pcfth->GetVtxDirCosZ();
    }
    
    return 0.0;
}


///
///
///
Double_t    TrackContext::GetMomentumSR() const
{
    const CandFitTrackHandle* pcfth =
        dynamic_cast<const CandFitTrackHandle*> (fCandTrackHandle);
    
    if ( pcfth ) {
        return pcfth->GetMomentumCurve();
    }
    
    return 0.0;
}


///
///
///
Double_t    TrackContext::GetMomentumRangeSR() const
{
    const CandFitTrackHandle* pcfth =
        dynamic_cast<const CandFitTrackHandle*> (fCandTrackHandle);
    
    if ( pcfth ) {
        return pcfth->GetMomentumRange();
    }
    
    return 0.0;
}


///
///
///
Int_t       TrackContext::GetIterationsSR() const
{
    const CandFitTrackHandle* pcfth =
        dynamic_cast<const CandFitTrackHandle*> (fCandTrackHandle);
    
    if ( pcfth ) {
        return pcfth->GetNIterate();
    }
    
    return 0;
}


///
///
///
Int_t       TrackContext::GetNdofSR() const
{
    const CandFitTrackHandle* pcfth =
        dynamic_cast<const CandFitTrackHandle*> (fCandTrackHandle);
    
    if ( pcfth ) {
        return pcfth->GetNDOF();
    }
    
    return 0;
}


///
///
///
Int_t       TrackContext::GetEMChargeSR() const
{
    const CandFitTrackHandle* pcfth =
        dynamic_cast<const CandFitTrackHandle*> (fCandTrackHandle);
    
    if ( pcfth ) {
        return static_cast<Int_t> (pcfth->GetEMCharge());
    }
    
    return 0;
}

