/**
 * Animation instance constructor.
 * Callable with two parameters, in such case its just image and its size holder, no positioning.
 * @param width 	Destination width (do scaling from zero to width)
 * @param height 	Destination height
 * @param speed 	Grow image size each iteration by <speed> percent. Use zero value to disable scaling or 'auto' for autoscale.
 * @param startLeft	
 * @param endLeft	
 * @param startTop	
 * @param endTop	
 * @param step 		Move image by <step> pixels on longer axis, 'shorter'-axis step is proportional. Use zero value to disable movement.
 */
Anim = function(width, height, speed, startLeft, endLeft, startTop, endTop, step, opacity) {
	this.scaleDone = true;
	this.moveDone = true;
	this.width = width;
	this.height = height;
	this.scale = 1;
	if (speed == undefined) {
		this.positioned = false;
		return this;
	}
	this.positioned = true;
	this.initSpeed = speed;
	this.opacity = opacity;
	this.lastOpacity = opacity;
	if (speed != 'auto') {
		this.speed = speed / 100;
	} else {
		this.speed = speed;
	}
	this.lastWidth = width;
	this.lastHeight = height;
	if (speed != 0) {
		this.scale = 0;
		this.scaleDone = false;
	}
	this.lastScale = this.scale;
	if (step != 0) {
		this.currentLeft = this.startLeft = this.lastLeft = startLeft;
		this.endLeft = endLeft;
		this.currentTop = this.startTop = this.lastTop = startTop;
		this.endTop = endTop;
		this.x = Math.abs(startLeft - endLeft);
		this.y = Math.abs(startTop - endTop);
		this.invertX = this.startLeft > this.endLeft;
		this.invertY = this.startTop > this.endTop;
		if (this.x > this.y) {
			this.leftStep = step;
			this.topStep = step * (this.y / this.x);
		} else {
			this.topStep = step;
			this.leftStep = step * (this.x / this.y);
		}
		this.lastLeft = this.currentLeft;
		this.lastTop = this.currentTop;
		this.moveDone = false;
	} else {
		/* disable movement */
		this.currentLeft = this.startLeft = this.endLeft = this.lastLeft = endLeft;
		this.currentTop = this.startTop = this.endTop = this.lastTop = endTop;
	}
};

Anim.prototype.isPositioned = function() {
	return this.positioned;
};

Anim.prototype.restart = function() {
	this.currentLeft = this.lastLeft = this.startLeft;
	this.currentTop = this.lastTop = this.startTop;
	this.scale = this.lastScale = 0;
	this.speed = this.initSpeed;
	this.moveDone = false;
	this.scaleDone = false;
};

Anim.prototype.setOpacity = function(opacity) {
	this.opacity = this.lastOpacity = opacity;
};

Anim.prototype.getOpacity = function() {
	return this.opacity;
};

Anim.prototype.interpolateOpacity = function(pct) {
	var iOpacity = this.opacity + (this.opacity - this.lastOpacity) * pct;
	if (iOpacity > 1) {
		iOpacity = 1;
	} else if (iOpacity < 0) {
		iOpacity = 0;
	}
	return iOpacity;
};

Anim.prototype.nextOpacity = function() {
	throw new Error('Not implemented.');
};

Anim.prototype.setStep = function(step) {
	if (this.x > this.y) {
		this.leftStep = step;
		this.topStep = step * (this.y / this.x);
	} else {
		this.topStep = step;
		this.leftStep = step * (this.x / this.y);
	}
};

Anim.prototype.isDone = function() {
	return (this.scaleDone && this.moveDone);
};

Anim.prototype.getWidth = function() {
	return this.width * this.scale;
};

Anim.prototype.getHeight = function() {
	return this.height * this.scale;
};

Anim.prototype.getScale = function() {
	return this.scale;
};

Anim.prototype.nextSize = function() {
	if (this.scaleDone) {
		return false;
	}
	this.lastScale = this.scale;
	if (this.speed == 0) {
		this.scaleDone = true;
		return false;
	}
	if (this.speed == 'auto') {
		if (this.x > this.y) {
			this.scale = Math.abs(this.currentLeft - this.startLeft) / this.x;
		} else {
			this.scale = Math.abs(this.currentTop - this.startTop) / this.y;
		}
	} else {
		this.scale += this.speed;
	}
	if (this.scale >= 1) {
		this.speed = 0;
		this.scale = 1;
	}
	return true;
};

Anim.prototype.getLeft = function() {
	return this.currentLeft;
};

Anim.prototype.getTop = function() {
	return this.currentTop;
};

Anim.prototype.nextPosition = function() {
	if (this.moveDone) {
		return false;
	}
	this.lastLeft = this.currentLeft;
	this.lastTop = this.currentTop;
	if ((this.currentLeft == this.endLeft) && (this.currentTop == this.endTop)) {
		this.moveDone = true;
		return false;
	}
	if (this.currentTop != this.endTop) {
		if (!this.invertY) {
			var temp = this.currentTop + this.topStep;
			if (temp < this.endTop) {
				this.currentTop = temp;
			} else {
				this.currentTop = this.endTop;
			}
		} else {
			var temp = this.currentTop - this.topStep;
			if (temp > this.endTop) {
				this.currentTop = temp;
			} else {
				this.currentTop = this.endTop;
			}
		}
	}
	if (this.currentLeft != this.endLeft) {
		if (!this.invertX) {
			var temp = this.currentLeft + this.leftStep;
			if (temp < this.endLeft) {
				this.currentLeft = temp;
			} else {
				this.currentLeft = this.endLeft;
			}
		} else {
			var temp = this.currentLeft - this.leftStep;
			if (temp > this.endLeft) {
				this.currentLeft = temp;
			} else {
				this.currentLeft = this.endLeft;
			}
		}
	}
	return true;
};

Anim.prototype.interpolateLeft = function(pct) {
	if (this.moveDone) {
		return this.endLeft;
	}
	var iLeft = this.currentLeft + (this.currentLeft - this.lastLeft) * pct;
	if ((this.invertX && (iLeft < this.endLeft)) || (!this.invertX && (iLeft > this.endLeft))) {
		iLeft = this.endLeft;
	}
	return iLeft;
};

Anim.prototype.interpolateTop = function(pct) {
	if (this.moveDone) {
		return this.endTop;
	}
	var iTop = this.currentTop + (this.currentTop - this.lastTop) * pct;
	if ((this.invertY && (iTop < this.endTop)) || (!this.invertY && (iTop > this.endTop))) {
		iTop = this.endTop;
	}
	return iTop;
};

Anim.prototype.interpolateWidth = function(pct) {
	if (this.scaleDone) {
		return this.width;
	}
	return this.width * this.interpolateScale(pct);
};

Anim.prototype.interpolateHeight = function(pct) {
	if (this.scaleDone) {
		return this.height;
	}
	return this.height * this.interpolateScale(pct);
};

Anim.prototype.interpolateScale = function(pct) {
	if (this.scaleDone) {
		return 1;
	}
	var iScale = this.scale + ((this.scale - this.lastScale) * pct); 
	if (iScale > 1) {
		iScale = 1;
	}
	return iScale; 
};

