/** 
* @file DecisionNode.h
* @brief decision node
* @author Erik Rodner
* @date 04/24/2008

*/
#ifndef DECISIONNODEINCLUDE
#define DECISIONNODEINCLUDE

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

#include <map>
#include <limits>

#include "vislearning/cbaselib/Feature.h"
#include "vislearning/math/mathbase/FullVector.h"


namespace OBJREC {

/** decision node: f(x) < threshold ? */
class DecisionNode
{
    public:

		/** threshold of the decision node */
		double threshold;

		/** counter which can be used to
		    count the number of examples which reached the node */
		double counter;

		/** the feature calculation method used for the
		    decision node */
		Feature *f;

		/** the empricical class distribution of the node:
		    under the condition that an example x reached this node
			what is the probability of x being from a class k */
		FullVector distribution;

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

		/** the right branch of the tree */
		DecisionNode *right;

		/** Indices of examples which were used to estimation
		    the class distribution during training. 
			Use this property with care! It should be set
			only for leafs and not in every case and for every
			decision tree building method */
		std::vector<int> trainExamplesIndices;

	public:

		/** constructor */
		DecisionNode ();
		
		/** traverse the tree and get the resulting leaf node */
		DecisionNode *getLeafNode ( const Example & ce, int depth = std::numeric_limits<int>::max() );

		/** traverse this node with an example */
		void traverse ( const Example & ce, FullVector & distribution );
		
		/** calculate the overall statistic of the current branch */
		void statistics ( int & depth, int & count ) const;
		 
		/** simple destructor */
		virtual ~DecisionNode();
	   

		/** only index descendants (with > depth), do not index node itsself */
		void indexDescendants ( std::map<DecisionNode *, std::pair<long, int> > & index, 
					long & maxindex,
					int depth ) const;

		/** reset the counters variable of the current branch */
		void resetCounters ();

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

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


} // namespace

#endif
