#ifndef MARS_MRanForest
#define MARS_MRanForest

#ifndef MARS_MParContainer
#include "MParContainer.h"
#endif

#ifndef ROOT_TArrayI
#include <TArrayI.h>
#endif

#ifndef ROOT_TArrayF
#include <TArrayF.h>
#endif

#ifndef ROOT_TArrayD
#include <TArrayD.h>
#endif

#ifndef ROOT_TObjArray
#include <TObjArray.h>
#endif

#ifndef ROOT_TRandom
#include <TRandom.h>
#endif

class MHMatrix;
class MRanTree;
class TVector;

class MRanForest : public MParContainer
{
private:
    Int_t fNumTrees;
    Int_t fTreeNo;

    MRanTree *fRanTree;
    TObjArray *fForest;

    // training data
    MHMatrix *fGammas;
    MHMatrix *fHadrons;

    Int_t   fNumGam;
    Int_t   fNumHad;
    Int_t   fNumData;
    Int_t   fNumDim;

    // true  and estimated hadronness
    TArrayI fHadTrue;
    TArrayF fHadEst;

    // data sorted according to parameters
    TArrayI fDataSort;
    TArrayI fDataRang;
    TArrayI fClassPop;

    // weights
    Bool_t  fUsePriors;
    TArrayF fPrior;
    TArrayF fWeight;
    TArrayI fNTimesOutBag;

    // estimates for classification error of growing forest
    TArrayD fTreeHad;
    Float_t fErr;

protected:
    // create and modify (->due to bagging) fDataSort
    void CreateDataSort();
    void ModifyDataSort(TArrayI &datsortinbag,Int_t ninbag,TArrayI &jinbag);

public:
    MRanForest(const char *name=NULL, const char *title=NULL);
    ~MRanForest();

    // initialize forest
    void SetPriors(Float_t prior_had, Float_t prior_gam);
    void SetNumTrees(Int_t n);

    // tree growing
    //void   SetupForest();
    Bool_t SetupGrow(MHMatrix *mhad,MHMatrix *mgam);
    Bool_t GrowForest();
    void SetCurTree(MRanTree *rantree) { fRanTree=rantree; }
    Bool_t AddTree(MRanTree *rantree);

    // getter methods
    TObjArray *GetForest() { return fForest; }
    MRanTree *GetCurTree() { return fRanTree; }
    Int_t      GetNumTrees() const { return fNumTrees; }
    Int_t      GetNumData() const { return fNumData; }
    Int_t      GetNumDim() const { return fNumDim; }
    Double_t   GetTreeHad(Int_t i) const { return fTreeHad.At(i); }
 
    // use forest to calculate hadronness of event
    Double_t CalcHadroness(const TVector &event);

    Bool_t AsciiWrite(ostream &out) const;

    ClassDef(MRanForest, 1) // Storage container for tree structure
};

#endif
