/// @file state.cc

#include "state.hh"

namespace EyeMind {

LogicalNodeBase::LogicalNodeBase() : Tagged()
{
	value = TRISTATE_UNKNOWN;
}


void LogicalNodeBase::Value(tristate v)
{
	if (v<0) {
		value = TRISTATE_FALSE;
		return;
	}

	if (v>0) {
		value = TRISTATE_TRUE;
		return;
	}

	value = TRISTATE_UNKNOWN;
}

void ANDNode::AND(tristate b)
{
	switch(b)
	{
	case(TRISTATE_TRUE):
		//value doesn't change
		break;

	case(TRISTATE_FALSE):
		value = TRISTATE_FALSE;
		break;

	case(TRISTATE_UNKNOWN):
		if(value==TRISTATE_TRUE)
			value = TRISTATE_UNKNOWN;
		break;
	}
}

tristate ANDNode::Evaluate()
{
#if 0 /// @bug does not work
	LogicalLink *link;

 	link = inlinks.Begin();
 
 	while(link!=NULL)
 	{
 		AND(link->Value());
 		link++;
 	}
#endif

	return value;
}

void ORNode::OR(tristate b)
{
	switch(b)
	{
	case(TRISTATE_TRUE):
		value = TRISTATE_TRUE;
		break;

	case(TRISTATE_FALSE):
		// value doesn't change
		break;

	case(TRISTATE_UNKNOWN):
		if(value==TRISTATE_FALSE)
			value = TRISTATE_UNKNOWN;
		break;
	}
}

tristate ORNode::Evaluate()
{
#if 0 /// @bug does not work
	LogicalLink *link;

 	link = inlinks.Begin();
 
 	while(link!=NULL)
 	{
 		OR(link->Value());
 		link++;
 	}
#endif

	return value;
}


tristate LogicalLink::Value()
{
	if(up!=NULL)
		return up->Value();
	else
		return TRISTATE_FALSE;
}


LogicalBranch::LogicalBranch()
{
	left = NULL;
	right = NULL;
}

State::State()
{
	up = NULL;
}


/// Connect SignalLink output with target State.
/// @warning: Use this only if you exactly know what you are doing and for
/// links that are already approved by some type-checking mechanism.

State& SignalLinkOutputToState(SignalLink& l, State& o)
{
	o.inlinks + l;  // add to inlinks of State
	return o; // make chaining possible (like stream)
}


/// Connect SignalLink input with source State.
/// @warning: Use this only if you exactly know what you are doing and for
/// links that are already approved by some type-checking mechanism.

State& SignalLinkInputToState(SignalLink& l, State& i)
{
	i.outlinks + l; // add to outlinks of State
	return i; // make chaining possible (like stream)
}


/// Add output SignalLink to State.
/// @warning: Use this only if you exactly know what you are doing and for
/// links that are already approved by some type-checking mechanism.

SignalLink& StateOutputToSignalLink(State& n, SignalLink& o)
{
	n.outlinks + o; // add to outlinks of State
	return o; // make chaining possible (like stream)
}


/// Add input SignalLink to State.
/// @warning: Use this only if you exactly know what you are doing and for
/// links that are already approved by some type-checking mechanism.

SignalLink& StateInputToSignalLink(State& n, SignalLink& i)
{
	n.inlinks + i; // add to inlinks of State
	return i; // make chaining possible (like stream)
}



State& operator>>(SignalLink& l, State& o)
{
	OSPanicIf(!l.Generic(),"Non-generic SignalLink attached as generic");
	return SignalLinkOutputToState(l,o);
}


State& operator<<(SignalLink& l, State& i)
{
	OSPanicIf(!l.Generic(),"Non-generic SignalLink attached as generic");
	return SignalLinkInputToState(l,i);
}


SignalLink& operator>>(State& n, SignalLink& o)
{
	OSPanicIf(!o.Generic(),"Non-generic SignalLink attached as generic");
	return StateOutputToSignalLink(n,o);
}


SignalLink& operator<<(State& n, SignalLink& i)
{
	OSPanicIf(!i.Generic(),"Non-generic SignalLink attached as generic");
	return StateInputToSignalLink(n,i);
}


}; // namespace EyeMind

