/**
 * @file RegressionTree.h
 * @brief regression tree implementation for regression
 * @author Sven Sickert
 * @date 06/19/2013

*/
#ifndef REGRESSIONTREEINCLUDE
#define REGRESSIONTREEINCLUDE

#include <map>
#include <set>

#include "core/vector/VectorT.h"
#include "core/vector/MatrixT.h"

#include "core/basics/triplet.h"
#include "core/basics/Config.h"
#include "core/basics/Persistent.h"
#include "vislearning/regression/randomforest/RegressionNode.h"

namespace OBJREC {

/** decision tree implementation for regression */
class RegressionTree : public NICE::Persistent
{
  protected:
    RegressionNode *root;
    const NICE::Config *conf; // for restore operation
    
  public:
    static void deleteNodes ( RegressionNode *tree );
    
    static RegressionNode *pruneTreeLeastSquares (
          RegressionNode *node,
          double minErrorReduction,
          double & lsError );
    
    /** simple consructor */
    RegressionTree( const NICE::Config *conf );
    
    /** simple destructor */
    virtual ~RegressionTree();
    
    void traverse ( const NICE::Vector & x,
          double & predVal );
    
    void resetCounters ();
    
    void statistics( int & depth, int & count ) const;
    
    void indexDescendants ( std::map<RegressionNode *, std::pair<long, int> > & index,
          long & maxindex ) const;

    RegressionNode *getLeafNode ( NICE::Vector & x,
          int maxdepth = 100000 );
    
    void getLeaves ( RegressionNode *node, std::vector<RegressionNode*> &leaves);
    
    std::vector<RegressionNode *> getAllLeafNodes ();
    
    RegressionNode *getRoot( ) const { return root; };
    
    void pruneTreeLeastSquares ( double minErrorReduction );
    
    void setRoot( RegressionNode *newroot );
    
    void restore (std::istream & is, int format = 0);
    void store (std::ostream & os, int format = 0) const;
    void clear ();
    

};


} // namespace

#endif