////////////////////////////////////////////////////////////////////////
// $Id: CandBase.h,v 1.28 2006/06/21 00:47:01 rhatcher Exp $
//
// CandBase.h
//
// CandBase is a virtual base class for Reconstruction Candidates.
//
// Each concrete CandBase must define a Dup function.
// CandBase must grant friendship to class CandRefer.
//
// Adapted from Babar's BtaCandBase (written by Gautier Hamel de
// Monchenault and Bob Jacobsen).
//
// Author:  G. Irwin 1/2000
////////////////////////////////////////////////////////////////////////

#ifndef CANDBASE_H
#define CANDBASE_H

#include "TNamed.h"
#include "TObjArray.h"                            // Needed for Root I/O
#include "TRef.h"

#include "CandData/CandRecord.h"                  // Needed for Root I/O
#include "Candidate/CandRefCounted.h"

class AlgConfig;
class AlgHandle;
class CandHandle;
class CandRefer;
class CandUid;
class VldContext;

class CandBase : public TNamed, public CandRefCounted
{

   friend class CandHandle;
   friend class CandRefer;
   friend class CandUid;

public:
   static Int_t GetNAlloc() {return fsNAlloc;}
   CandBase();                                         // Public for I/O

   virtual void Trace(const char *c = "") const;

   virtual std::ostream& FormatToOStream(std::ostream& os,
                                             Option_t *option="") const;
   virtual std::ostream& FormatDaughtersToOStream(std::ostream& os,
                                             Option_t *option="") const;

protected:
   TRef fAlgConfigRef;                              // TRef to AlgConfig
   CandRecord *fCandRecord;             // Associated CandRecord pointer
   TObjArray fDaughters;            // TObjArray of daughter CandHandles
   CandHandle *fLocalHandle;            // Endpoint of daughter pointers

   CandBase(const AlgHandle &ah);
   CandBase(const CandBase &cb);
   virtual ~CandBase();

   const CandHandle *AddDaughterLink(const CandHandle &ch);
   virtual void CreateLocalHandle() = 0;
   virtual CandBase *Dup() const = 0;
   AlgConfig *GetAlgConfig() const;
   UInt_t GetArchUidInt() const;
   const CandUid &GetCandUid() const {return *fCandUid;}
   const CandHandle *GetDaughter(Int_t ndau) const;
   TIter GetDaughterIterator() const;
   const CandHandle *GetLocalHandle() const {return fLocalHandle;}
   Int_t GetNDaughters() const;
   UInt_t GetUidInt() const;
   Bool_t HasOverlapWith(const CandBase &cb) const;
   Bool_t IsComposite() const;
   virtual Bool_t IsEquivalent(const TObject* rhs) const;
   Bool_t RemoveDaughter(CandHandle *ch);
   void SetCandRecord(CandRecord *cr);
   void SetLocalHandle(CandHandle *ch); // Called from CreateLocalHandle

// Test methods called from IsEquivalent methods of CandBase derived
// classes.  For Candidate Validation suite by Paul Echevarria, Oct 2003
template<class mType>
Bool_t TestArrayEquality(const char* mbrName, int arrLen,
                         const mType& thisMbr,
                         const mType& rhsMbr) const;

template<class chType>
Bool_t TestCandHandleDup(const char* chName,
                         const chType* thisCH,
                         const chType* rCndCH ) const;

template<class _char>
  void TestDisplayCandBanner(_char* mName) const;

template<class mType>
Bool_t TestEquality(const char* mbrName,
                    const mType& thisMbr,
                    const mType& rhsMbr) const;

template<class mType>
Bool_t TestEquivalence(const char* mName,
                       const mType& thisMbr,
                       const mType& rhsMbr) const;

template<class elemType>
Bool_t TestGenericElemPtrTObjArrayPtrEquality(const char* arrName,
                                               const TObjArray* thisTOA,
                                        const TObjArray* rCndTOA) const;

template<class elemType>
Bool_t TestGenericElemPtrTObjArrayPtrEquivalence(const char* arrName,
                                               const TObjArray* thisTOA,
                                               const TObjArray* rCndTOA,
                                     Bool_t testEquivalence=true) const;

template<class _char>
void TestNothing(_char* mName = "Candidate") const;

template<class mType>
Bool_t TestPtrEquivalence(const char* mName,
                          const mType* thisMbr,
                          const mType* rhsMbr) const;

template<class toaType>
Bool_t TestTObjArrayCandHandleDup(const char* arrName,
                                  const toaType& thisTOA,
                                  const toaType& rCndTOA) const;

template<class toaType>
Bool_t TestTObjArrayEquality(const char* arrName,
                             const toaType& thisTOA,
                             const toaType& rCndTOA) const;

template<class toaType>
Bool_t TestTObjArrayPtrEquality(const char* arrName,
                                const toaType* thisTOA,
                                const toaType* rCndTOA) const;

template<class toaType>
Bool_t TestTObjArrayPtrEquivalence(const char* arrName,
                                   const toaType* thisTOA,
                                   const toaType* rCndTOA,
                                   Bool_t testEquivalence=true) const;

// Indentation levels for FormatToOStream
 static const TString& GetIndentString() { return fgIndentString; } 
 static const TString& GetDataIndent()   { return fgDataIndentString; }
 static void           SetDataIndent(const TString& distr) 
   { fgDataIndentString=distr;}
 static Int_t    DecIndent() 
   { --fgIndentLevel; return ResizeIndent(); }
 static Int_t    IncIndent() 
   { ++fgIndentLevel; return ResizeIndent(); }


private:
   UInt_t fArchUidInt;                //! Immediate Ancestor Cand UIDInt
   CandUid *fCandUid;                          //! Unique Cand ID object
   static Int_t fsNAlloc;        // Current number of CandBase instances
   CandBase &operator=(const CandBase &);          // Should not be used


   static Int_t   fgIndentLevel;                 // current indent level
   static TString fgIndentString;         // current indent level string
   static TString fgDataIndentString;  // additnl indent for data values

   static Int_t   ResizeIndent();

ClassDef(CandBase,2)              // Reconstruction Candidate Base Class

};

#if defined(MACOSX) && (__GNUC__ <= 3)
  #include "Candidate/CandBase.tpl"
#endif

#endif                                                     // CANDBASE_H
