/*
 *	Animator class 
 *	Use to call a method over a period of time with a value that determines progress.
 *	Useful for animating stuff :)
 */


Animator = function (startValue, endValue, f, t, r) {
	this.step  = 10;	    //The step by which timer counts from 0 to 100
	this.rate  = 10;	    //The rate in ms at which steps are taken
	this.power = 2;         //The steepness of the animation curve
	this.type  = this.NONE; //The type of easing

	this.min = startValue;
	this.max = endValue;
	this.isReversing = false;
	this.animateFunction = f;
	this.terminateFunction = t;
	this.reversalFunction = r;

	this.precalc = new Array(100);
	for (var i=0; i <= 100; i++)
		this.precalc[i] = this.calculate(i);
}
Animator.prototype.NONE      = 0;
Animator.prototype.EASEIN    = 1;
Animator.prototype.EASEOUT   = 2;
Animator.prototype.EASEINOUT = 3;

Animator.prototype.setStep = function (step) {
	this.step = step;
}
Animator.prototype.setRate = function (rate) {
	this.rate = rate;
}
Animator.prototype.setPower = function (power) {
	this.power = power;
	for (var i=0; i <= 100; i++)
		this.precalc[i] = this.calculate(i);
}
Animator.prototype.setType = function (type) {
	this.type = type;
	for (var i=0; i <= 100; i++)
		this.precalc[i] = this.calculate(i);
}
Animator.prototype.setAnimateFunction = function (f) {
	this.animateFunction = f;
}
Animator.prototype.start = function () {
	if (this.interval) return;
	this.time = 0;
	this.isReversing = false;
	this.interval = setInterval(this.method(this.animate), this.rate);
}
Animator.prototype.reverse = function () {
	this.isReversing = (this.isReversing) ? false : true;
}
Animator.prototype.stop = function () {
	if (this.interval)
		clearInterval(this.interval);
	this.interval = null;
}
Animator.prototype.pause = function () {
	//this.paused = true;
	if (this.interval)
		clearInterval(this.interval);
}
Animator.prototype.resume = function () {
	//this.paused = false;
	this.interval = setInterval(this.method(this.animate), this.rate);
}
Animator.prototype.isAnimating = function () {
	return Boolean(this.interval);
}
Animator.prototype.animate = function () {
	if (this.time >= 0 && this.time <= 100) {
		this.animateFunction(this.precalc[this.time]);
		this.time = (this.isReversing) ? this.time - this.step : this.time + this.step;
	} else {
		clearInterval(this.interval);
		this.interval = null;
		if (!this.isReversing && this.terminateFunction)
			this.terminateFunction();
		if (this.isReversing && this.reversalFunction)
			this.reversalFunction();
	}
}
Animator.prototype.calculate = function (t) {
	t = t/100;
	var factor;
	switch (this.type) {
		case this.NONE      : factor = this.easeNone(t);break;
		case this.EASEIN    : factor = this.easeIn(t);break;
		case this.EASEOUT   : factor = this.easeOut(t);break;
		case this.EASEINOUT : factor = this.easeInOut(t);break;
	}
	return parseInt(this.min + factor*(this.max-this.min));
}
Animator.prototype.easeNone = function (t) {
	return t;
}
Animator.prototype.easeIn = function (t) {
	return Math.pow(t,this.power);
}
Animator.prototype.easeOut = function (t) {
	return 1-this.easeIn(1-t);
}
Animator.prototype.easeInOut = function (t) {
	if (t < 0.5)
		return this.easeIn(t*2)/2;
	return 0.5+this.easeOut((t-0.5)*2)/2;
}
