// Animator
/* usage
		var element=document.getElementById('yourelement');
		element=element.style;
		var property='width';
		var begin=element.style.width;
		var change=100;
		var time=20;
		var type='inCirc';
		
		var youranimator=new Animator(element:Object,property:String,begin:Number,change:Number,time:Number[,type:Sring]);
		youranimator.addListener(listener:Object,method:String);
		youranimator.run();
*/
phocus.Animator=function(element,property,begin,change,time,type)
{
	this.element=element;
	this.property=property;
	this.begin=begin;
	this.change=change;
	this.time=0;
	this.ttime=time;
	this.type=type;
	this.transform='';
	this.method=null;
	this.object=null;
	
	// listeners details
	this.listeners=new Array();
	
	// if the passed type doesn't exist as a function, set a default type
	if(!this[type])
		this.type='inOutCirc';
}
$pr=phocus.register(phocus.Animator);
// object properties

// registration functions
$pr.register=function(object,method)
{
	this.object=object;
	this.method=method;
}

// animation functions
// t: current time, b: beginning value, c: change in position, d: duration
$pr.inCirc=function(t,b,d,c)
{
	return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
}
$pr.outCirc=function(t,b,d,c)
{
	return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
}
$pr.inOutCirc=function(t,b,d,c)
{
	if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
	return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
}
$pr.inExpo = function (t,b,d,c)
{
	return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
}
$pr.outExpo = function (t,b,d,c)
{
	return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
}
$pr.inOutExpo = function (t,b,d,c)
{
	if (t==0) return b;
	if (t==d) return b+c;
	if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
	return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
}

// run - responsible for running the animator each tick
$pr.run=function(delay)
{
	if(typeof delay != 'number')
		var delay=0;
	this.run=phocus.Runtime.addrun(this,'execute',null,delay,this.ttime,this,'end');
}
$pr.escape=function()
{
	this.run.r=0;
}
// execute
$pr.execute=function(t,tt)
{
	var _t=tt-t;
	var prop=this[this.type](_t,this.begin,tt,this.change);
	if(this.round==true)
		prop=Math.floor(prop);
	if(this.transform!='')
		prop=this.transform.split('%%val%%').join(prop);
	
	if(typeof this.method == 'string' && typeof this.object != 'undefined')
		this.object[this.method](prop,this.element,this.property);
	else
		this.element[this.property]=prop;
}
// end
$pr.end=function()
{
	for(var i in this.listeners)
		this.listeners[i].listener[this.listeners[i].method](this.change-this.begin,this.element,this.property);
	clearInterval(this.timer);
}
$pr.kill=function()
{
	this.run.escape();
	clearInterval(this.timer);
	this.listeners=null;
}

// adding and removing listeners
$pr.addListener=function(listener,method)
{
	this.listeners.push({listener:listener,method:method});
}
$pr.removelistener=function(listener,method)
{
	for(var i=this.listeners.length-1;i>=0;i--)
	{
		var op=this.listeners[i];
		if(op.listener==listener && op.method==method)
		{
			this.listeners.splice(i,1);
			break;
		}
	}
}
