/*
* Animation by equation
* ----------------------------------------
* @last_modified: 2007-08-23
* @author: Filatov Dmitry <alpha@design.ru>
* ----------------------------------------
*/

function AnimationEquation(
	oElement,
	oParams
	) {

	AnimationEquation.baseConstructor.call(this);

	this.oElement = oElement;

	this.oParams = Common.Object.extend(
		oParams,
		AnimationEquation.DEFAULT_CONFIG
		);

	this.oElementStyle = oElement && this.oParams.sProperty? oElement.style : null;
	this.sProperty = this.oParams.sProperty;
	this.sUnit = this.oParams.sUnit;
	this.fEquation = this.oParams.fEquation;
	this.iFramesCount = this.oParams.iFramesCount;
	this.dValueStart = this.dValueCurrent = this.oParams.dValueStart;
	this.dValueEnd = this.oParams.dValueEnd;
	this.dValueDiff = this.dValueEnd - this.dValueStart;
	this.iFrameCurrent = 0;
	if(this.oParams.fCallbackFunction) {
		this.setCallbackFunction(this.oParams.fCallbackFunction);
	}

	if(this.oParams.fStopCallbackFunction) {
		this.setStopCallbackFunction(this.oParams.fStopCallbackFunction);
	}

}

AnimationEquation.DEFAULT_CONFIG = {

	sProperty             : 'left',
	sUnit                 : 'px',
	fEquation             : null,
	iFramesCount          : 10,
	dValueStart           : 0,
	dValueEnd             : 10,
	fCallbackFunction 	  : null,
	fStopCallbackFunction : null

};

AnimationEquation.inheritFrom(
	Animation,
	{

		getValueCurrent : function() {

			return this.dValueCurrent;

		},

		getFrameCurrent : function() {

			return this.iFrameCurrent;

		},

		doProcess : function() {

			this.iFrameCurrent++;

			this.dValueCurrent = this.fEquation(
				this.iFrameCurrent,
				this.dValueStart,
				this.dValueDiff,
				this.iFramesCount
				);

			if(this.oElementStyle) {
				this.setProperty(this.dValueCurrent);
			}

		},

		shouldStop : function() {

			return this.iFrameCurrent >= this.iFramesCount;

		},

		setProperty : function(dValue) {

			this.oElementStyle[this.sProperty] = dValue + this.sUnit;

		}

	}
	);


AnimationEquation.linear = function(t, b, c, d){

	return c*t/d + b;

};

AnimationEquation.Quadratic = {

	easeIn : function(t, b, c, d) {

		return c*(t/=d)*t + b;

	},

	easeOut : function(t, b, c, d) {

		return c*(t/=d)*t + b;

	},

	easeInOut : function(t, b, c, d) {

		if((t/=d/2) < 1) {
			return c/2*t*t + b;
		}

		return -c/2 * ((--t)*(t-2) - 1) + b;

	}

};

AnimationEquation.Cubic = {

	easeIn : function(t, b, c, d) {

		return c*(t/=d)*t*t + b;

	},

	easeOut : function(t, b, c, d) {

		return c*((t=t/d-1)*t*t + 1) + b;

	},

	easeInOut : function(t, b, c, d) {

		if((t/=d/2) < 1) {
			return c/2*t*t*t + b;
		}

		return c/2*((t-=2)*t*t + 2) + b;

	}

};

AnimationEquation.Quartic = {

	easeIn : function(t, b, c, d) {

		return c*(t/=d)*t*t*t + b;

	},

	easeOut : function(t, b, c, d) {

		return -c * ((t=t/d-1)*t*t*t - 1) + b;

	},

	easeInOut : function(t, b, c, d) {

		if((t/=d/2) < 1) {
			return c/2*t*t*t*t + b;
		}

		return -c/2 * ((t-=2)*t*t*t - 2) + b;

	}

};

AnimationEquation.Quintic = {

	easeIn : function(t, b, c, d) {

		return c*(t/=d)*t*t*t*t + b;

	},

	easeOut : function(t, b, c, d) {

		return c*((t=t/d-1)*t*t*t*t + 1) + b;

	},

	easeInOut : function(t, b, c, d) {

		if((t/=d/2) < 1) {
			return c/2*t*t*t*t*t + b;
		}

		return c/2*((t-=2)*t*t*t*t + 2) + b;
	}

};

AnimationEquation.Sine = {

	easeIn : function(t, b, c, d) {

		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;

	},

	easeOut : function(t, b, c, d) {

		return c * Math.sin(t/d * (Math.PI/2)) + b;

	},

	easeInOut : function(t, b, c, d) {

		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;

	}

};

AnimationEquation.Exponential = {

	easeIn : function(t, b, c, d) {

		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;

	},

	easeOut : function(t, b, c, d) {

		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;

	},

	easeInOut : function(t, b, c, d) {

		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;

	}

};

AnimationEquation.Circular = {

	easeIn : function(t, b, c, d) {

		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;

	},

	easeOut : function(t, b, c, d) {

		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;

	},

	easeInOut : function(t, b, c, d) {

		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;

	}

};

AnimationEquation.Elastic = {

	easeIn : function(t, b, c, d) {

		var
			s = 1.70158,
			p = 0,
			a = c
			;

		if(t==0) {
			return b;
		}

		if((t/=d)==1) {
			return b+c;
		}

		if(!p) {
			p = d*.3;
		}

		if(a < Math.abs(c)) {
			a = c;
			s = p/4;
		}
		else {
			s = p/(2*Math.PI) * Math.asin(c/a);
		}

		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;

	},

	easeOut : function(t, b, c, d, a, p) {

		var
			s = 1.70158,
			p = 0,
			a = c
			;

		if(t==0) {
			return b;
		}

		if((t/=d)==1) {
			return b+c;
		}

		if(!p) {
			p = d*.3;
		}

		if(a < Math.abs(c)) {
			a = c;
			s = p/4;
		}
		else {
			s = p/(2*Math.PI) * Math.asin (c/a);
		}

		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
	},

	easeInOut : function(t, b, c, d, a, p) {

		var
			s = 1.70158,
			p = 0,
			a = c
			;

		if(t==0) {
			return b;
		}

		if((t/=d/2)==2) {
			return b+c;
		}

		if(!p) {
			p=d*(.3*1.5);
		}

		if(a < Math.abs(c)) {
			a=c;
			s=p/4;
		}
		else {
			s = p/(2*Math.PI) * Math.asin (c/a);
		}

		if(t < 1) {
			return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
		}

		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;

	}

};

AnimationEquation.Back = {

	easeIn: function(t, b, c, d, s) {

		if(s == null) {
			s = 1.70158;
		}

		return c*(t/=d)*t*((s+1)*t - s) + b;

	},

	easeOut: function(t, b, c, d, s) {

		if(s == null) {
			s = 1.70158;
		}

		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;

	},

	easeInOut: function(t, b, c, d, s) {

		if(s == null) {
			s = 1.70158;
		}

		if((t/=d/2) < 1) {
			return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
		}

		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;

	}

};

AnimationEquation.Bounce = {

	easeIn: function(t, b, c, d) {

		return c - AnimationEquation.Bounce.easeOut(d-t, 0, c, d) + b;

	},

	easeOut: function(t, b, c, d) {

		if((t/=d) < (1/2.75)) {
			return c*(7.5625*t*t) + b;
		}

		if(t < (2/2.75)) {
			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
		}

		if (t < (2.5/2.75)) {
			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
		}

		return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;

	},

	easeInOut: function(t, b, c, d) {

		if(t < d/2) {
			return AnimationEquation.Bounce.easeIn(t*2, 0, c, d) * 0.5 + b;
		}

		return AnimationEquation.Bounce.easeOut(t*2-d, 0, c, d) * 0.5 + c*0.5 + b;

	}

};
