/**
 * @file RegressionNode.h
 * @brief regression node
 * @author Sven Sickert
 * @date 06/19/2013

*/
#ifndef REGRESSIONNODEINCLUDE
#define REGRESSIONNODEINCLUDE

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

#include <map>
#include <limits>

namespace OBJREC {
  
/** regression node: f(x) < threshold ? */
class RegressionNode
{
  protected:
  
  public:
    
    /** threshold of the regression node */
    double threshold;
    
    /** counter which can be used to
        count the number of examples which reached the node */
    double counter;
    
    /** the feature used for the regression node split */
    int f;
    
    /** the least squares error of the node */
    double lsError;
    
    /** the prediction value of the node */
    double predVal;

    /** the left branch of the tree */
    RegressionNode *left;

    /** the right branch of the tree */
    RegressionNode *right;
    
    /** Indices of examples which were used to estimate the
     * prediction value during training */
    std::vector<int> trainExamplesIndices;

    /** constructor */
    RegressionNode ();
    
    /** simple destructor */
    virtual ~RegressionNode();
    
    /** traverse the tree and get the resulting leaf node */
    RegressionNode *getLeafNode ( const NICE::Vector & x,
          int depth = std::numeric_limits<int>::max() );

    /** traverse this node with an example */
    void traverse ( const NICE::Vector & x,
          double & predVal );
    
    /** calculate the overall statistic of the current branch */
    void statistics ( int & depth, int & count ) const;
     
    /** only index descendants (with > depth), do not index node itsself */
    void indexDescendants ( std::map<RegressionNode *,
          std::pair<long, int> > & index, 
          long & maxindex,
          int depth ) const;

    /** calculate the prediction value for this node */
    void nodePrediction( const NICE::Vector & y,
          const std::vector<int> & selection);
    
    /** reset the counters variable of the current branch */
    void resetCounters ();

    /** copy the node information to another node */
    void copy ( RegressionNode *node );

    /** is this node a leaf */
    bool isLeaf () const;
};
  
  
} // namespace

#endif