////////////////////////////////////////////////////////////////////////
// $Id: CandTrackSR.cxx,v 1.27 2005/02/02 17:17:01 tagg Exp $
//
// CandTrackSR
//
// This is a concrete Event Candidate (Reconstruction) object.
// CandTrackSR is descended from CandTrack.
//
// Each concrete CandBase must define a Dup function.
// CandBase must grant friendship to class CandRefer.
//
// Author:  R. Lee 2001.02.26
////////////////////////////////////////////////////////////////////////

#include "TClass.h"
#include "TObjArray.h"

#include "Algorithm/AlgHandle.h"
#include "CandTrackSR/CandTrackSR.h"
#include "CandTrackSR/CandTrackSRHandle.h"
#include "MessageService/MsgService.h"

ClassImp(CandTrackSR)

//______________________________________________________________________
CVSID("$Id: CandTrackSR.cxx,v 1.27 2005/02/02 17:17:01 tagg Exp $");

#include "Candidate/CandBase.tpl"

//______________________________________________________________________
CandTrackSR::CandTrackSR() :
  fClusterList(0),
  fUTrack(0),
  fVTrack(0),
  fNTrackStrip(0),
  fNTrackDigit(0),
  fNTimeFitDigit(0),
  fTimeFitChi2(0.)
{
  MSG("Cand", Msg::kDebug)
                    << "Begin CandTrackSR::CandTrackSR() ctor: " << endl
                                           << "UidInt = " << GetUidInt()
                           << ", ArchUidInt " << GetArchUidInt() << endl
                             << "No. of links = " << GetNLinks() << endl
                      << "End CandTrackSR::CandTrackSR() ctor." << endl;
}

//______________________________________________________________________
CandTrackSR::CandTrackSR(AlgHandle &ah) :
  CandTrack(ah),     // Should be the next class up on inheritance chain
  fClusterList(0),
  fUTrack(0),
  fVTrack(0),
  fNTrackStrip(0),
  fNTrackDigit(0),
  fNTimeFitDigit(0),
  fTimeFitChi2(0.)
{

// The sole purpose of this constructor is to transmit the AlgHandle
// up the inheritance chain to CandBase without having to invoke the
// full constructor of an intermediate Candidate type which the highest
// level Candidate might inherit from.  One only wants to create the
// LocalHandle and invoke the RunAlg() method in the lowest level class.
}

//______________________________________________________________________
CandTrackSR::CandTrackSR(AlgHandle &ah, CandHandle &ch,
                                                      CandContext &cx) :
  CandTrack(ah),     // Should be the next class up on inheritance chain
  fClusterList(0),
  fUTrack(0),
  fVTrack(0),
  fNTrackStrip(0),
  fNTrackDigit(0),
  fNTimeFitDigit(0),
  fTimeFitChi2(0.)
{
  CreateLocalHandle();
  MSG("Cand", Msg::kDebug)
         << "Begin CandTrackSR::CandTrackSR(AlgHandle &, CandHandle &, "
                                      << "CandContext &) ctor: " << endl
                                           << "UidInt = " << GetUidInt()
                           << ", ArchUidInt " << GetArchUidInt() << endl
                             << "No. of links = " << GetNLinks() << endl
           << "End CandTrackSR::CandTrackSR(AlgHandle &, CandHandle &, "
                                      << "CandContext &) ctor." << endl;

  fClusterList = new TObjArray;

// Run Algorithm to construct Candidate
  {                                                   // Start of scope.
    CandTrackSRHandle csh(this);             // csh will go out of scope
    ch = csh;                                       // after setting ch.
  }                                                     // End of scope.
  ah.RunAlg(ch, cx);
}

//______________________________________________________________________
CandTrackSR::CandTrackSR(const CandTrackSR &rhs) :
  CandTrack(rhs)     // Should be the next class up on inheritance chain
, fClusterList(0)                        // Made a deep copy from vers 6
, fUTrack(new Track2DSR(*rhs.fUTrack))     //gmi: Supposedly a deep copy
, fVTrack(new Track2DSR(*rhs.fVTrack))     //gmi: Supposedly a deep copy
, fNTrackStrip(rhs.fNTrackStrip)
, fNTrackDigit(rhs.fNTrackDigit)
, fNTimeFitDigit(rhs.fNTimeFitDigit)
, fTimeFitChi2(rhs.fTimeFitChi2)
{

//CreateLocalHandle(); // Moved to Dup function following copy-ctor call
  MSG("Cand", Msg::kDebug)
       << "Begin CandTrackSR::CandTrackSR(const CandTrackSR &rhs) ctor:"
                                   << endl << "UidInt = " << GetUidInt()
                           << ", ArchUidInt " << GetArchUidInt() << endl
                             << "No. of links = " << GetNLinks() << endl
         << "End CandTrackSR::CandTrackSR(const CandTrackSR &rhs) ctor."
                                                                << endl;

// fClusterList contents owned from CandTrackSR version 6
  if (rhs.fClusterList) {
    fClusterList = new TObjArray;
    CandHandle *ch;
    TIter cliter(rhs.fClusterList);
    while ((ch = dynamic_cast<CandHandle *>(cliter())))
      fClusterList->Add(ch->DupHandle());
  }
}

//______________________________________________________________________
CandTrackSR::~CandTrackSR()
{
  MSG("Cand", Msg::kDebug)
                   << "Begin CandTrackSR::~CandTrackSR() dtor: " << endl
                                           << "UidInt = " << GetUidInt()
                           << ", ArchUidInt " << GetArchUidInt() << endl
                             << "No. of links = " << GetNLinks() << endl
                     << "End CandTrackSR::~CandTrackSR() dtor." << endl;

  if (fClusterList) {
    fClusterList->Delete();  // Owned CandHandle*'s from CandTrackSR v 6
    delete fClusterList;
  }
    delete fUTrack;
    delete fVTrack;
}

//______________________________________________________________________
void CandTrackSR::CreateLocalHandle()
{
  SetLocalHandle(new CandTrackSRHandle(this));
}

//______________________________________________________________________
CandTrackSR *CandTrackSR::Dup() const
{

// Base copy ctor dups owned pointers, but defers copying Daughter List.
// Daughter List copy is made in the derived class Dup() function.
// This is because base class copy constructor hasn't yet created
// fLocalHandle with a CandHandle* of the full derived type.
  CandTrackSR *cb = new CandTrackSR(*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;
}

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

  result = TestGenericElemPtrTObjArrayPtrEquality<CandClusterHandle>(
                                        "fClusterList",
                                        this->fClusterList,
                                        rCnd->fClusterList)   && result;
  result = TestPtrEquivalence("fUTrack",
                                        this->fUTrack,
                                        rCnd->fUTrack)        && result;
  result = TestPtrEquivalence("fVTrack",
                                        this->fVTrack,
                                        rCnd->fVTrack)        && result;
  result = TestEquality("fNTrackStrip", this->fNTrackStrip,
                                        rCnd->fNTrackStrip)   && result;
  result = TestEquality("fNTrackDigit", this->fNTrackDigit,
                                        rCnd->fNTrackDigit)   && result;
  result = TestEquality("fNTimeFitDigit",
                                        this->fNTimeFitDigit,
                                        rCnd->fNTimeFitDigit) && result;
  result = TestEquality("fTimeFitChi2", this->fTimeFitChi2,
                                        rCnd->fTimeFitChi2)   && result;

  return result;
}

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

//______________________________________________________________________
void CandTrackSR::Streamer(TBuffer &R__b)
{

// Stream an object of class CandTrackSR.
  if (R__b.IsReading()) {
    UInt_t R__s, R__c;
    Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
    CandTrackSR::Class()->ReadBuffer(R__b, this, R__v, R__s, R__c);
    if (R__v < 6) {

// fClusterList contents owned from CandTrackSR version 6
      if (fClusterList) {
        CandHandle *ch;
        TIter cliter(fClusterList);
        while ((ch = dynamic_cast<CandHandle *>(cliter())))
          fClusterList->AddAt(ch->DupHandle(),
                                             fClusterList->IndexOf(ch));
      }
    }
  }
  else {
    CandTrackSR::Class()->WriteBuffer(R__b, this);
  }
}
