////////////////////////////////////////////////////////////////////////
// $Id: CandFitTrackSR.cxx,v 1.25 2005/12/07 14:15:55 musser Exp $
//
// CandFitTrackSR
//
// This is a concrete Event Candidate (Reconstruction) object.
// CandFitTrackSR is descended from CandFitTrack.
//
// Each concrete CandBase must define a Dup function.
// CandBase must grant friendship to class CandRefer.
//
// Author:  R. Lee 2001.03.30
////////////////////////////////////////////////////////////////////////

#include "Algorithm/AlgConfig.h"
#include "Algorithm/AlgHandle.h"
#include "CandFitTrackSR/CandFitTrackSR.h"
#include "CandFitTrackSR/CandFitTrackSRHandle.h"
#include "CandFitTrackSR/KalmanPlaneSR.h"
#include "MessageService/MsgService.h"

ClassImp(CandFitTrackSR)

//______________________________________________________________________
CVSID("$Id: CandFitTrackSR.cxx,v 1.25 2005/12/07 14:15:55 musser Exp $");

#include "Candidate/CandBase.tpl"

//______________________________________________________________________
CandFitTrackSR::CandFitTrackSR() :
  fInitialQP(0.),
  fNChangedFitPoint(0)
{
  Init();
}

//______________________________________________________________________
CandFitTrackSR::CandFitTrackSR(AlgHandle &ah) :
  CandFitTrack(ah),  // Should be the next class up on inheritance chain
  fInitialQP(0.),
  fNChangedFitPoint(0)
{
  Init();
}

//______________________________________________________________________
CandFitTrackSR::CandFitTrackSR(AlgHandle &ah, CandHandle &ch,
                                                      CandContext &cx) :
  CandFitTrack(ah),  // Should be the next class up on inheritance chain
  fInitialQP(0.),
  fNChangedFitPoint(0)
{
  CreateLocalHandle();
 
  Init();
// Run Algorithm to construct Candidate
  {                                                    // Start of scope
    CandFitTrackSRHandle csh(this);          // csh will go out of scope
    ch = csh;                                       // after setting ch.
  }                                                      // End of scope
  ah.RunAlg(ch, cx);
}

//______________________________________________________________________
CandFitTrackSR::CandFitTrackSR(const CandFitTrackSR &rhs) :
  CandFitTrack(rhs), // Should be the next class up on inheritance chain
  fInitialQP(rhs.fInitialQP),
  fNChangedFitPoint(rhs.fNChangedFitPoint)
{

  Init();
  fVtxExtrapolate[0] = rhs.fVtxExtrapolate[0];
  fVtxExtrapolate[1] = rhs.fVtxExtrapolate[1];
  fEndExtrapolate[0] = rhs.fEndExtrapolate[0];
  fEndExtrapolate[1] = rhs.fEndExtrapolate[1];
  for (int i=0; i<=rhs.fTrackClusterList->GetLast(); i++) {
    TrackClusterSR *tc =
            dynamic_cast<TrackClusterSR*>(rhs.fTrackClusterList->At(i));
    TrackClusterSR *newtc = new TrackClusterSR(*tc);
    fTrackClusterList->Add(newtc);
  }
  for (int i=0; i<=rhs.fPlaneList->GetLast(); i++) {
    KalmanPlaneSR *kp =
                    dynamic_cast<KalmanPlaneSR*>(rhs.fPlaneList->At(i));
    KalmanPlaneSR *newkp = new KalmanPlaneSR(kp);
    fPlaneList->Add(newkp);
  }

  map<TrackClusterSR *,Bool_t>::iterator fBadFitIter;
  map<Int_t,Float_t>::iterator fPlanePreChi2Iter;

  for (fBadFitIter = rhs.fBadFit.begin();
                        fBadFitIter!=rhs.fBadFit.end(); fBadFitIter++) {
    fBadFit[fBadFitIter->first] = fBadFitIter->second;
  }

  for (fPlanePreChi2Iter = rhs.fPlanePreChi2.begin();
      fPlanePreChi2Iter!=rhs.fPlanePreChi2.end(); fPlanePreChi2Iter++) {
    fPlanePreChi2[fPlanePreChi2Iter->first] = fPlanePreChi2Iter->second;
  }


  fdUdZ.erase(fdUdZ.begin(),fdUdZ.end());
  map<Int_t,Float_t>::iterator fdUdZIter;
  for (fdUdZIter = rhs.fdUdZ.begin(); fdUdZIter!=rhs.fdUdZ.end();
                                                          fdUdZIter++) {
    fdUdZ[fdUdZIter->first] = fdUdZIter->second;
  }

  fdVdZ.erase(fdVdZ.begin(),fdVdZ.end());
  map<Int_t,Float_t>::iterator fdVdZIter;
  for (fdVdZIter = rhs.fdVdZ.begin(); fdVdZIter!=rhs.fdVdZ.end();
                                                          fdVdZIter++) {
    fdVdZ[fdVdZIter->first] = fdVdZIter->second;
  }
}

//______________________________________________________________________
CandFitTrackSR::~CandFitTrackSR()
{
  if (fPlaneList) {
    for (Int_t i=0; i<=fPlaneList->GetLast(); i++) {
      KalmanPlaneSR *kp =
                        dynamic_cast<KalmanPlaneSR*>(fPlaneList->At(i));
      delete kp;
    }
    delete fPlaneList;
  }
  if (fTrackClusterList) {
    for (Int_t i=0; i<=fTrackClusterList->GetLast(); i++) {
      TrackClusterSR *tc =
                dynamic_cast<TrackClusterSR*>(fTrackClusterList->At(i));
      delete tc;
    }
    delete fTrackClusterList;
  }
}

//______________________________________________________________________
void CandFitTrackSR::CreateLocalHandle()
{
  SetLocalHandle(new CandFitTrackSRHandle(this));
}

//______________________________________________________________________
CandFitTrackSR *CandFitTrackSR::Dup() const
{
  CandFitTrackSR *cb = new CandFitTrackSR(*this); // Copy-ctor dups ptrs
  cb->CreateLocalHandle();   // Initializes fLocalHandle after copy-ctor
  TIter iterdau = GetDaughterIterator();
  CandHandle *dau;
  while ((dau=(CandHandle *) iterdau())) cb->AddDaughterLink(*dau);
  return cb;
}

//______________________________________________________________________
void CandFitTrackSR::Init()
{
  fPlaneList = new TObjArray;
  fPlaneList->Clear();
  fPlaneList->Compress();
  fTrackClusterList = new TObjArray;
  fTrackClusterList->Clear();
  fTrackClusterList->Compress();
  fCurrent = 0;
  fCurrentU = 0;
  fCurrentV = 0;
  fVtxExtrapolate[0] = 0;
  fVtxExtrapolate[1] = 0;
  fEndExtrapolate[0] = 0;
  fEndExtrapolate[1] = 0;
}

//______________________________________________________________________
Bool_t CandFitTrackSR::IsEquivalent(const TObject *rhs) const
{
  Bool_t result = true;
  if (!CandFitTrack::IsEquivalent(rhs)) result = false;    // superclass
  TestDisplayCandBanner("CandFitTrackSR");
  const CandFitTrackSR* rCnd = dynamic_cast<const CandFitTrackSR*>(rhs);
  if (rCnd == NULL) return false;

  result = TestGenericElemPtrTObjArrayPtrEquivalence<KalmanPlaneSR>(
                            "fPlaneList",
                            this->fPlaneList,
                            rCnd->fPlaneList, kTRUE)          && result;
  result = TestGenericElemPtrTObjArrayPtrEquivalence<TrackClusterSR>(
                            "fTrackClusterList",
                            this->fTrackClusterList,
                            rCnd->fTrackClusterList, kTRUE)   && result;
  result = TestPtrEquivalence("fCurrent",
                            this->fCurrent, 
                            rCnd->fCurrent)                   && result;
  result = TestPtrEquivalence("fCurrentU",
                            this->fCurrentU, 
                            rCnd->fCurrentU)                  && result;
  result = TestPtrEquivalence("fCurrentV",
                            this->fCurrentV, 
                            rCnd->fCurrentV)                  && result;
  result = TestEquality("fInitialQP",
                            this->fInitialQP,
                            rCnd->fInitialQP)                 && result;
  result = TestEquality("fNChangedFitPoint",
                            this->fNChangedFitPoint,
                            rCnd->fNChangedFitPoint)          && result;
  result = TestArrayEquality("fVtxExtrapolate", 2,
                            this->fVtxExtrapolate,
                            rCnd->fVtxExtrapolate)            && result;
  result = TestArrayEquality("fEndExtrapolate", 2,
                            this->fEndExtrapolate,
                            rCnd->fEndExtrapolate)            && result;
  result = TestEquality("fBadFit",       this->fBadFit, 
                                         rCnd->fBadFit)       && result;
  result = TestEquality("fPlanePreChi2", this->fPlanePreChi2, 
                                         rCnd->fPlanePreChi2) && result;
  result = TestEquality("fdUdZ",         this->fdUdZ, 
                                         rCnd->fdUdZ)         && result;
  result = TestEquality("fdVdZ",         this->fdVdZ, 
                                         rCnd->fdVdZ)         && result;

  return result;  
}

//______________________________________________________________________
CandFitTrackSRHandle CandFitTrackSR::MakeCandidate(AlgHandle &ah,
                                                        CandContext &cx)
{
  CandFitTrackSRHandle csh;
  new CandFitTrackSR(ah, csh, cx);    // csh owns the new CandFitTrackSR
  return csh;
}

//______________________________________________________________________
std::ostream& CandFitTrackSR::FormatToOStream(std::ostream& os,
                                           Option_t *option) const
{
  CandFitTrack::FormatToOStream(os,option);

  TString opt(option);
  if (!opt.Contains("v0")) { // v0 means suppress the data values
    const TString& indent = GetIndentString();

    os << indent << GetDataIndent()
       << "QP Initial " << fInitialQP
       << " NChangedFitPoint " << fNChangedFitPoint
       << endl;

    os << indent << "...should have print routines for KalmanPlaneSR" << endl;
  }
  return os;
  
}

//______________________________________________________________________
