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

*/
#include <iostream>

#include "core/image/ImageT.h"
#include "core/imagedisplay/ImageDisplay.h"

#include "vislearning/classifier/fpclassifier/randomforest/DecisionNode.h"

using namespace OBJREC;

using namespace std;
using namespace NICE;


DecisionNode::~DecisionNode()
{
    if ( f != NULL )
	delete f;
}

DecisionNode::DecisionNode ()
{
    left = NULL;
    right = NULL;
    f = NULL;
    counter = 0;
}

DecisionNode *DecisionNode::getLeafNode (
		    const Example & ce,
		    int depth )
{
    counter += ce.weight;
    if ( (!depth) || ((left == NULL) && (right == NULL)) )
	return this;
    
    double val = f->val( &ce );
    if ( val < threshold )
		if ( left != NULL )
			return left->getLeafNode ( ce, depth - 1 );
		else
			return this;
    else
		if ( right != NULL )
			return right->getLeafNode ( ce, depth - 1 );
		else
			return this;

}

void DecisionNode::traverse ( 
		    const Example & ce, 
		    FullVector & _distribution )
{
    DecisionNode *leaf = getLeafNode ( ce );
    _distribution = leaf->distribution;
}



void DecisionNode::statistics ( int & depth, int & count ) const
{
    int dl, cl;
    if ( left != NULL )
    {
		left->statistics ( dl, cl );
		dl++;
	} else {
		dl = 0;
		cl = 0;
    }
    
    if ( right != NULL )
    {	
		right->statistics ( depth, count );
		depth++;
    } else {
		depth = 0;
		count = 0;
    }

    depth = (depth > dl) ? depth : dl;
    count += cl + 1;
}
    
void DecisionNode::indexDescendants ( map<DecisionNode *, pair<long, int> > & index, long & maxindex, int depth ) const
{
    if ( left != NULL )
    {
		maxindex++;
		index.insert ( pair<DecisionNode *, pair<long, int> > ( left, pair<long, int>( maxindex, depth + 1 ) ) );
		left->indexDescendants ( index, maxindex, depth+1 );
    }

    if ( right != NULL )
    {
		maxindex++;
		index.insert ( pair<DecisionNode *, pair<long, int> > ( right, pair<long, int>( maxindex, depth + 1 ) ) );
		right->indexDescendants ( index, maxindex, depth+1 );
    }
}

void DecisionNode::resetCounters ()
{
    counter = 0;
    if ( left != NULL ) left->resetCounters();
    if ( right != NULL ) right->resetCounters();
}


void DecisionNode::copy ( DecisionNode *node )
{
    left = node->left;
    right = node->right;
    threshold = node->threshold; 
    f = node->f;
    distribution = node->distribution;
	trainExamplesIndices = node->trainExamplesIndices;
}

bool DecisionNode::isLeaf () const
{
    return ( (right == NULL) && (left == NULL) );
}