/**
 * Encapsulates the context of a function allowing its invocation at a delayed
 * time.
 */
DelayedFunction = function ()
{
	//String representing the function invocation.
	//It's arguments may be written as $#arg0#, $#arg1#, ..., $#argN#.
	//This arguments are later binded to the objects passed with bindArgument.
	this.functionString = null;
	
	//The object where the function will be called.
	//Null if the function is global.
	this.caller = null;
	
	//The list of arguments that will be binded when invoking the function.
	this.arguments = new Array();
}

/**
 * Returns the invocation string.
 */
DelayedFunction.prototype.getFunctionString = function ()
{
	return this.functionString;
}

/**
 * Sets the invocation string.
 */
DelayedFunction.prototype.setFunctionString = function (newString)
{
	this.functionString = newString;
}

/**
 * Return the object where the invocation will be done.
 */
DelayedFunction.prototype.getCaller = function ()
{
	return this.caller;
}

/**
 * Sets the object where the invocation will be done.
 */
DelayedFunction.prototype.setCaller = function (newCaller)
{
	this.caller = newCaller;
}

/**
 * Return the list of objects tha will be binded as arguments of the function.
 */
DelayedFunction.prototype.getArguments = function ()
{
	return this.arguments;
}

/**
 * Binds an object as an argument of the function.
 */
DelayedFunction.prototype.bindArgument = function (newArgument)
{
	this.arguments.push(newArgument);
}

/**
 * Executes the function
 */
DelayedFunction.prototype.run = function ()
{
	var call = this.getFunctionString();
	var args = this.getArguments();

	//bind the arguments
	for (var i = 0; i < args.length; i++)
	{
		call = call.replace("$#arg" + i + "#", "args[" + i + "]");
	}

	//invoke on the caller object
	if (this.getCaller() != null)
	{
		call = "this.getCaller()." + call;
	}
	
	eval(call);
}
