/*!
 *  \brief Get the value of the first argument.
 *  \param outResult Value of the first argument.
 *  \param ioContext Evolutionary context.
 *  \throw Beagle::AssertException If there is no argument to the primitive.
 *  \throw Beagle::GP::MaxNodesExecutionException If number of nodes execution is more than allowed.
 *  \throw Beagle::GP::MaxTimeExecutionException If elapsed execution time is more than allowed.
 */
inline void Beagle::GP::Primitive::get1stArgument(Beagle::GP::Datum& outResult,
        Beagle::GP::Context& ioContext)
{
	Beagle_StackTraceBeginM();
	using namespace Beagle;
	Beagle_AssertM(getNumberArguments() >= 1);
	unsigned int lNodeIndex = ioContext.getCallStackTop() + 1;
	ioContext.incrementNodesExecuted();
	ioContext.checkExecutionTime();
	ioContext.pushCallStack(lNodeIndex);
	Beagle_LogDebugM(
	    ioContext.getSystem().getLogger(),
	    "primitive", "Beagle::GP::Primitive",
	    std::string("Executing the primitive '")+
	    ioContext.getGenotype()[lNodeIndex].mPrimitive->getName()+std::string("' of the ")+
	    uint2ordinal(lNodeIndex+1)+std::string(" node of the ")+
	    uint2ordinal(ioContext.getGenotypeIndex()+1)+" tree"
	);
	ioContext.getGenotype()[lNodeIndex].mPrimitive->execute(outResult, ioContext);
	Beagle_LogDebugM(
	    ioContext.getSystem().getLogger(),
	    "primitive", "Beagle::GP::Primitive",
	    std::string("Result of executing '")+
	    ioContext.getGenotype()[lNodeIndex].mPrimitive->getName()+std::string("': ")+
	    outResult.serialize()
	);
	ioContext.popCallStack();
	Beagle_StackTraceEndM("void GP::Primitive::get1stArgument(GP::Datum& outResult, GP::Context& ioContext)");
}
/*!
 *  \brief Get the value of the arguments.
 *  \param outResults Value of the arguments. Array of the good size must be allocated.
 *  \param inSizeTDatum Size (in byte) of each datum of the array.
 *  \param ioContext Evolutionary context.
 *  \throw Beagle::AssertException If the size of the bag doesn't match the nb. of arguments.
 *  \throw Beagle::GP::MaxNodesExecutionException If number of nodes execution is more than allowed.
 *  \throw Beagle::GP::MaxTimeExecutionException If elapsed execution time is more than allowed.
 */
inline void Beagle::GP::Primitive::getArguments(Beagle::GP::Datum outResults[],
        size_t inSizeTDatum,
        Beagle::GP::Context& ioContext)
{
	Beagle_StackTraceBeginM();
	using namespace Beagle;
	char* lCharResults = reinterpret_cast<char*>(outResults);
	GP::Tree& lActualTree = ioContext.getGenotype();
	unsigned int lNodeIndex = ioContext.getCallStackTop() + 1;
	ioContext.incrementNodesExecuted();
	ioContext.checkExecutionTime();
	ioContext.pushCallStack(lNodeIndex);
	lActualTree[lNodeIndex].mPrimitive->execute(*outResults, ioContext);
	ioContext.popCallStack();
	for(unsigned int i=1; i<mNumberArguments; i++) {
		lNodeIndex += lActualTree[lNodeIndex].mSubTreeSize;
		ioContext.incrementNodesExecuted();
		ioContext.checkExecutionTime();
		ioContext.pushCallStack(lNodeIndex);
		GP::Datum* lResultsI = reinterpret_cast<GP::Datum*>(lCharResults + (i*inSizeTDatum));
		Beagle_LogDebugM(
		    ioContext.getSystem().getLogger(),
		    "primitive", "Beagle::GP::Primitive",
		    std::string("Executing the primitive '")+
		    lActualTree[lNodeIndex].mPrimitive->getName()+std::string("' of the ")+
		    uint2ordinal(lNodeIndex+1)+std::string(" node of the ")+
		    uint2ordinal(ioContext.getGenotypeIndex()+1)+" tree"
		);
		lActualTree[lNodeIndex].mPrimitive->execute(*lResultsI, ioContext);
		ioContext.popCallStack();
	}
	Beagle_StackTraceEndM("void GP::Primitive::getArguments(GP::Datum outResults[], size_t inSizeTDatum, GP::Context& ioContext)");
}
/*!
 *  \brief Get the value of the nth argument.
 *  \param inN Index of the argument to get.
 *  \param outResult Value of the nth argument.
 *  \param ioContext Evolutionary context.
 *  \throw Beagle::AssertException If the argument index is invalid.
 *  \throw Beagle::GP::MaxNodesExecutionException If number of nodes execution is more than allowed.
 *  \throw Beagle::GP::MaxTimeExecutionException If elapsed execution time is more than allowed.
 */
inline void Beagle::GP::Primitive::getArgument(unsigned int inN,
        Beagle::GP::Datum& outResult,
        Beagle::GP::Context& ioContext)
{
	Beagle_StackTraceBeginM();
	using namespace Beagle;
	Beagle_UpperBoundCheckAssertM(inN,mNumberArguments-1);
	GP::Tree& lActualTree = ioContext.getGenotype();
	unsigned int lNodeIndex = getArgumentIndex(inN, ioContext);
	ioContext.incrementNodesExecuted();
	ioContext.checkExecutionTime();
	ioContext.pushCallStack(lNodeIndex);
	Beagle_LogDebugM(
	    ioContext.getSystem().getLogger(),
	    "primitive", "Beagle::GP::Primitive",
	    std::string("Executing the primitive '")+
	    lActualTree[lNodeIndex].mPrimitive->getName()+std::string("' of the ")+uint2ordinal(lNodeIndex+1)+
	    std::string(" node of the ")+uint2ordinal(ioContext.getGenotypeIndex()+1)+" tree"
	);
	lActualTree[lNodeIndex].mPrimitive->execute(outResult, ioContext);
	ioContext.popCallStack();
	Beagle_StackTraceEndM("void GP::Primitive::getArgument(unsigned int inN, GP::Datum& outResult, GP::Context& ioContext)");
}
void DCDCBoostEmbryo::execute(Beagle::GP::Datum& outDatum, Beagle::GP::Context& ioContext) {
	//RootReturn& lReturnID = castObjectT<RootReturn&>(outDatum);
	BGContext& lContext = castObjectT<BGContext&>(ioContext);
	GrowingHybridBondGraph::Handle lGrowingBondGraph = new GrowingHybridBondGraph();
	DCDCBoostLookaheadController *lController = new DCDCBoostLookaheadController;
	
	
	//Get the parameters
	Beagle::Component::Handle lHolderComponent = ioContext.getSystem().getComponent("ParametersHolder");
	if(lHolderComponent==NULL)
		throw Beagle_RunTimeExceptionM("No CMA holder component found in the system!");
	ParametersHolder::Handle lHolder = castHandleT<ParametersHolder>(lHolderComponent);
	if(lHolder==NULL)
		throw Beagle_RunTimeExceptionM("Component named \"ParameterHolder\" found is not of the good type!");
	
#ifdef SINGLE_OUTPUT
	//Creating the bond graph embryo
	
	//Create the sources
	std::vector<Source*> lS(1);
	for(unsigned int i = 0; i < lS.size(); ++i) {
		lS[i] = new Source(Source::eEffort);
		lS[i]->setValue(1.5);
		lHolder->push_back(lS[i]);
		lGrowingBondGraph->addComponent(lS[i]);
	}
	
	std::vector<Junction*> lJ0(1);
	for(unsigned int i = 0; i < lJ0.size(); ++i) {
		lJ0[i] = new Junction(Junction::eZero);
		lGrowingBondGraph->addComponent(lJ0[i]);
	}
	
	std::vector<Passive*> lR(1);
	for(unsigned int i = 0; i < lR.size(); ++i) {
		lR[i] = new Passive(Passive::eResistor);
		lHolder->push_back(lR[i]);
		lGrowingBondGraph->addComponent(lR[i]);
	}
	lR[0]->setValue(6);
	
	//Create the bonds
	std::vector<Bond*> lEffortOutputBonds(1);
	std::vector<Bond*> lFlowtOutputBonds(1);
	std::vector<Bond*> lArgBonds(2);
	
	lArgBonds[0] = lGrowingBondGraph->connect(lS[0],lJ0[0]);
	lArgBonds[1] = lGrowingBondGraph->connect(lJ0[0],lR[0]);
	lEffortOutputBonds[0] = lArgBonds[1];
	lFlowtOutputBonds[0] = lArgBonds[0];
#else
	//Creating the bond graph embryo for the double output
	
	//Create the sources
	std::vector<Source*> lS(1);
	for(unsigned int i = 0; i < lS.size(); ++i) {
		lS[i] = new Source(Source::eEffort);
		lS[i]->setValue(1.5);
		lHolder->push_back(lS[i]);
		lGrowingBondGraph->addComponent(lS[i]);
	}
	
	std::vector<Junction*> lJ0(1);
	for(unsigned int i = 0; i < lJ0.size(); ++i) {
		lJ0[i] = new Junction(Junction::eZero);
		lGrowingBondGraph->addComponent(lJ0[i]);
	}
	
	std::vector<Passive*> lR(2);
	for(unsigned int i = 0; i < lR.size(); ++i) {
		lR[i] = new Passive(Passive::eResistor);
		lHolder->push_back(lR[i]);
		lGrowingBondGraph->addComponent(lR[i]);
	}
	lR[0]->setValue(6.25);
	lR[1]->setValue(34.1);
	
	//Create the bonds
	std::vector<Bond*> lEffortOutputBonds(2);
	std::vector<Bond*> lFlowtOutputBonds(1);
	std::vector<Bond*> lArgBonds(3);
	
	lArgBonds[0] = lGrowingBondGraph->connect(lS[0],lJ0[0]);
	lArgBonds[1] = lGrowingBondGraph->connect(lJ0[0],lR[0]);
	lArgBonds[2] = lGrowingBondGraph->connect(lJ0[0],lR[1]);
	lEffortOutputBonds[0] = lArgBonds[1];
	lEffortOutputBonds[1] = lArgBonds[2];
	lFlowtOutputBonds[0] = lArgBonds[0];
	
#endif
	
	lGrowingBondGraph->setOutputBonds(lEffortOutputBonds,lFlowtOutputBonds);
		
 	lGrowingBondGraph->addSwitchController(lController);
	lGrowingBondGraph->postConnectionInitialization();
	
	lContext.setBondGraph(lGrowingBondGraph);
	
	//For each modifable site a subtree can be parsed.
	std::vector<JunctionPtr> lJctPtr(1);
	for(unsigned int i = 0; i < lJctPtr.size(); ++i) {
		lJctPtr[i].setValue(lJ0[i]);
		getArgument(i,lJctPtr[i],ioContext);
	}	
	std::vector<BondPtr> lBondPtr(lArgBonds.size());
	for(unsigned int i = 0; i < lBondPtr.size(); ++i) {
		lBondPtr[i].setValue(lArgBonds[i]);
		getArgument(i+lJctPtr.size(),lBondPtr[i],ioContext);
	}
	
}