// Animator
/* usage
		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();
*/
com.saltcollective.Phocus.Animator=function(begin,change,time,type,alert)
{
	this.begin=begin;
	this.change=change;
	this.time=0;
	this.ttime=time;
	this.type=type;
	this.transform='';
	this.round=false;
	
	this.alert=alert;
	
	// if the passed type doesn't exist as a function, set a default type
	if(!this[type])
		this.type='linear';
		
	// event listeners Array
	this.listeners={};
}
$pr=com.saltcollective.Phocus.Animator.prototype;

// 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;
}
$pr.linear = function(t,b,d,c)
{
	return c*t/d+b;
}

// events
$pr.onstart=function(object,method,args)
{
	return this.addlistener('onstart',object,method,args);
}
$pr.onerror=function(object,method,args)
{
	return this.addlistener('onerror',object,method,args);
}
$pr.ontick=function(object,method,args)
{
	return this.addlistener('ontick',object,method,args);
}
$pr.onend=function(object,method,args)
{
	return this.addlistener('onend',object,method,args);
}
$pr.onkill=function(object,method,args)
{
	return this.addlistener('onkill',object,method,args);
}
// private function
// add listener
$pr.addlistener=function(event,object,method,args)
{
	if(typeof object != 'object' || typeof method != 'string')
		return false;
		
	if(typeof this.listeners[event] == 'undefined')
		this.listeners[event]=[];
	
	// replaced below because IE sucks
//	if(!phocus.Util.isinstanceof(args,Array))
	if(typeof args != 'object' || typeof args.length != 'number')
		var args=[];
	
	this.listeners[event].push({object:object,method:method,args:args});
	
	return true;
}
// private function
// dispatch event
$pr.dispatchevent=function(event,data)
{
	try
	{
		typeof this.listeners[event]
	} catch(e)
	{
		return;
	}
	var group=this.listeners[event];
	for(var i in group)
	{
		var args=[data];
		for(var j=0;j<group[i].args.length;j++)
			args.push(group[i].args[j]);
		group[i].object[group[i].method].apply(group[i].object,args);
	}
}

// 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',null,this,'start');
}
$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);
	
	this.dispatchevent('ontick',prop);
}
// end
$pr.start=function()
{
	this.dispatchevent('onstart');
}
$pr.end=function()
{
	this.dispatchevent('onend');
	clearInterval(this.timer);
}
$pr.kill=function()
{
//	console.log('I\' dead');
	this.dispatchevent('onkill',1);
	this.run.escape();
	clearInterval(this.timer);
	this.listeners=null;
}
com.saltcollective.Phocus.register(com.saltcollective.Phocus.Animator,'Animator');

$pr=null;
