// JavaScript Document

function AnimationObject(object) {
	this.object = null;
	this.id = null;
	
	this.allowPositionChange = false; // change to positionChange
	this.allowSizeChange = false;
	this.allowAlphaChange = false;
	
	
	this.actionsArray = new Array();
	this.callBack = null;
	this.callBackListener = null;
	
	this.defaultX = null;
	this.defaultY = null;
	this.defaultW = null;
	this.defaultH = null;
	this.defaultA = null;
	
	this.x = null;
	this.y = null;
	this.w = null;
	this.h = null;
	this.a = null;
	
	this.tweenX = null;
	this.tweenY = null;
	this.tweenW = null;
	this.tweenH = null;
	this.tweenA = null;
	
	this.currentFrame = 0;
	this.totalFrames = 0;
	
	this.tweenPlay = false;
	this.tweenDone = false;
	
	this.tweenEase = 0;
	
	this.Init = function(object) {
		this.object = $(object);
		
		if(!this.object) {
			alert("AnimationObject: Object not found");
			return false;
		}

		var x = parseInt(this.getStyleProperty("left"));
		var y = parseInt(this.getStyleProperty("top"));
		
		if(x+1) {
			this.defaultX = this.x = x;
		} else {
			this.defaultX = this.x = getX(this.object);
		}
		
		if(y+1) {
			this.defaultY = this.y = y;
		} else {
			this.defaultY = this.y = getY(this.object);
		}
		
		var paddingTop = parseInt(this.getStyleProperty("padding-top"));
		var paddingBottom = parseInt(this.getStyleProperty("padding-bottom"));
		var paddingLeft = parseInt(this.getStyleProperty("padding-left"));
		var paddingRight = parseInt(this.getStyleProperty("padding-right"));
		
		if(paddingLeft || paddingRight) {
			this.defaultW = this.w = this.object.offsetWidth - paddingLeft - paddingRight;
		} else {
			this.defaultW = this.w = this.object.offsetWidth;
		}
		
		if(paddingTop || paddingBottom) {
			this.defaultH = this.h = this.object.offsetHeight - paddingTop - paddingBottom;
		} else {
			this.defaultH = this.h = this.object.offsetHeight;
		}
		
		if(this.isIE) {
			var filter = this.getStyleProperty("filter");
			this.defaultA = this.a = (filter) ? parseInt(filter.substr(String(filter.indexOf("=")+1))) : 100;
		} else {
			var opacity = (this.getStyleProperty("opacity") || this.getStyleProperty("-moz-opacity"));
			this.defaultA = this.a = (opacity+1) ? opacity*100 : 100;
		}
	}
	
	this.checkInit = function() {
		var x = parseInt(this.getStyleProperty("left"));
		var y = parseInt(this.getStyleProperty("top"));
		
		if(x+1) {
			this.defaultX = this.x = x;
		} else {
			this.defaultX = this.x = getX(this.object);
		}
		
		if(y+1) {
			this.defaultY = this.y = y;
		} else {
			this.defaultY = this.y = getY(this.object);
		}
	}
	
	this.setAction = function(actionObj) {
		this.actionsArray.push(actionObj);
	}
	
	this.setCallBack = function(callBackFunc, listener) {
		this.callBack = callBackFunc;
		if(listener)
			this.callBackListener = listener;
		else 
			this.callBackListener = null;
	}
	
	this.animate = function() {
		if(this.tweenPlay) {		
			if(this.tweenA[this.currentFrame]) {
				//alert(this.tweenA[this.currentFrame] + "\n" + this.currentFrame + "\n" + this.totalFrames);
			}
			
			this.setDimensions(this.tweenX[this.currentFrame], this.tweenY[this.currentFrame], this.tweenW[this.currentFrame], this.tweenH[this.currentFrame], this.tweenA[this.currentFrame]);
			this.refresh();
			
			this.currentFrame++;
			
			if(this.currentFrame >= this.totalFrames) {
				this.tweenPlay = false;
				this.tweenDone = true;
				if(this.callBack) {
					if(this.callBackListener) {
						this.callBack.call(this.callBackListener, this.object);
					} else {
						this.callBack(this.object);
					}
				}
				return false;
			}
		}
		
		return true;
	}
		
	this.setDimensions = function(x,y,w,h,a) {
		this.x = (x+1)?x:this.x;
		this.y = (y+1)?y:this.y;
		this.w = (w+1)?w:this.w;
		this.h = (h+1)?h:this.h;
		this.a = (a+1)?a:this.a;
	}
	
	this.refresh = function() {
		if(this.allowPositionChange) {
			this.object.style.left = this.x+"px";
			this.object.style.top = this.y+"px";
		}
		if(this.allowSizeChange) {
			this.object.style.width = this.w+"px";
			this.object.style.height = this.h+"px";
		}
		if(this.allowAlphaChange) this.changeAlpha(this.a);
	}
	
	this.createTween = function() {
		this.currentFrame = 0;

		this.tweenX = new Array();
		this.tweenY = new Array();
		this.tweenW = new Array();
		this.tweenH = new Array();
		this.tweenA = new Array();
		for(var i=0; i<this.actionsArray.length; i++) {
			var action = this.actionsArray[i];
			if(this.totalFrames < action.tweenFrames) this.totalFrames = action.tweenFrames;
			switch(action.method) {
				case "moveTo":
					this.allowPositionChange = true;
					this.moveTo(action.x, action.y, action.tweenFrames, action.delayFrames, action.ease);
					break;
				case "resizeTo":
					this.allowSizeChange = true;
					this.resizeTo(action.width, action.height, action.tweenFrames, action.delayFrames, action.ease);
					break;
				case "fadeIn":
					this.allowAlphaChange = true;
					this.fadeIn(action.alpha, action.tweenFrames, action.delayFrames, action.ease)
					break;
				case "fadeOut":
					this.allowAlphaChange = true;
					this.fadeOut(action.alpha, action.tweenFrames, action.delayFrames, action.ease)
					break;					
				case "fade":
					this.allowAlphaChange = true;
					this.fade(this.a, action.alpha, action.tweenFrames, action.delayFrames, action.ease)
					break;
				case "revertSize":
					this.revertSize(action.tweenFrames, action.delayFrames, action.ease)
					break;
			}
		}
	}
	
	
	this.moveTo = function(x, y, tweenFrames, delayFrames, ease) {
		if(!ease) {
			if(x+1) this.tweenX = this.Tween(this.x, x, tweenFrames);
			if(y+1) this.tweenY = this.Tween(this.y, y, tweenFrames);
		} else {
			if(x+1) this.tweenX = this.Ease(this.x, x, tweenFrames, ease);
			if(y+1) this.tweenY = this.Ease(this.y, y, tweenFrames, ease);
		}
	}
	
	this.resizeTo = function(width, height, tweenFrames, delayFrames, ease) {
		if(!ease) {
			if(width+1) this.tweenW = this.Tween(this.w, width, tweenFrames);
			if(height+1) this.tweenH = this.Tween(this.h, height, tweenFrames);
		} else {
			if(width+1) this.tweenW = this.Ease(this.w, width, tweenFrames, ease);
			if(height+1) this.tweenH = this.Ease(this.h, height, tweenFrames, ease);
		}
	}
	
	this.fadeIn = function(alpha, tweenFrames, delayFrames, ease) {
		this.fade(0, alpha, tweenFrames, delayFrames, ease);
	}
	
	this.fadeOut = function(alpha, tweenFrames, delayFrames, ease) {
		this.fade(100, alpha, tweenFrames, delayFrames, ease);
	}
	
	this.revertSize = function(tweenFrames, delayFrames, ease) {
		if(!ease) {
			this.tweenW = this.Tween(this.w, this.defaultW, tweenFrames);
			this.tweenH = this.Tween(this.h, this.defaultH, tweenFrames);
		} else {
			this.tweenW = this.Ease(this.w, this.defaultW, tweenFrames, ease);
			this.tweenH = this.Ease(this.h, this.defaultH, tweenFrames, ease);
		}
	}
	
	this.fade = function(alphaStart, alphaEnd, tweenFrames, delayFrames, ease) {
		if(alphaEnd+1) {
			if(!ease)
				this.tweenA = this.Tween(alphaStart, alphaEnd, tweenFrames);
			else
				this.tweenA = this.Ease(alphaStart, alphaEnd, tweenFrames, ease);
		}
	}
	
	this.Tween = function(minValue, maxValue, totalFrames) {
		var delta = maxValue - minValue;
		var valueArray = new Array();
		valueArray.push(minValue);
		for(var i = 1; i < totalFrames-1; i++ ) {
			valueArray.push( minValue + Math.ceil((delta/(totalFrames-1))*i) );
		}
		
		valueArray.push(maxValue);

		return valueArray;
	}
	
	this.Ease = function(minValue, maxValue, totalFrames, ease) {
		var delta = maxValue - minValue;
		var valueArray = new Array();
		valueArray.push(minValue);
		for(var i = 1; i < totalFrames-1; i++ ) {
			valueArray.push( Math.ceil(minValue+(Math.pow(((1 / (totalFrames-1))*i),ease)*delta)) );
		}
		
		valueArray.push(maxValue);
		//alert(valueArray.toString() + "\n" + valueArray.length + "\n" + totalFrames);
		return valueArray;
	}
	
	this.changeAlpha = function (alpha) {
		this.object.style.opacity = (alpha / 100);
		this.object.style.MozOpacity = (alpha / 100);
		//this.object.style.KhtmlOpacity = (opacity / 100);
		this.object.style.filter = "alpha(opacity=" + alpha + ")";
	}
	
	this.isOpera = (navigator.userAgent.toLowerCase().indexOf('opera')+1?1:0);
	this.isIE = (navigator.appName.toLowerCase().indexOf('internet explorer')+1?1:0);
	if(this.isOpera) this.isIE = false;
	this.isSafari = (navigator.appVersion.toLowerCase().indexOf('safari')+1?1:0);

	this.getStyleProperty = function(cssProperty) {
		if (this.object.currentStyle) {
			cssProperty = this.getIECSSProperty(cssProperty);
			return this.object.currentStyle[cssProperty];
		} else if (window.getComputedStyle) {
			return document.defaultView.getComputedStyle(this.object,null).getPropertyValue(cssProperty);
		}
	}
	
	this.getIECSSProperty = function(cssProperty) {
		var propertyArray = new Array();
		propertyArray["padding-top"] = "paddingTop";
		propertyArray["padding-bottom"] = "paddingBottom";
		propertyArray["padding-left"] = "paddingLeft";
		propertyArray["padding-right"] = "paddingRight";
		return (propertyArray[cssProperty])?propertyArray[cssProperty]:cssProperty;
	}
	
	this.Init(object);
	
}

function AnimationControlObject(animObjectId) {
	this.anim = getAnimationManager();
	this.objectId = animObjectId;
	
	this.setAction = function(actionObj) {
		this.anim.getObjectById(this.objectId).setAction({
															method: actionObj.method,
															x: actionObj.x,
															y: actionObj.y,
															width: actionObj.width,
															height: actionObj.height,
															alpha: actionObj.alpha,
															tweenFrames: Math.ceil(actionObj.duration/this.anim.getIntervalValue()),
															delayFrames: Math.ceil(actionObj.delay/this.anim.getIntervalValue()),
															ease: actionObj.ease
															});
	}
	
	this.setCallBack = function(functionName, listener) {
		this.anim.getObjectById(this.objectId).setCallBack(functionName, listener);
	}
	
	this.play = function() {
		this.anim.addToQueue(this.objectId);
	}
}

function AnimationManager() {
	this.queue = new Array();
	this.objectsArray = new Array();
	this.objectsIdCount = 0;
	this.queueInterval = null;
	this.framePerSecond = 25;
	
	this.add = function(object, resizeOnly) {
		var newAnimObject = this.findObject(object);
		
		if(newAnimObject == null) {
			newAnimObject = new AnimationObject(object);
			if(newAnimObject.object) {
				newAnimObject.id = this.objectsIdCount++;
				this.objectsArray.push(newAnimObject);
			}
		} else {
			newAnimObject.checkInit();
		}
		
		if(newAnimObject.object) {
			return this.getControlObject(newAnimObject.id);		
		}
		
		return null;
	}
	
	this.addToQueue = function(animObjectId) {
		var animObject = this.getObjectById(animObjectId);
		if(animObject) {
			animObject.tweenPlay = true;
			animObject.tweenDone = false;
			animObject.createTween();
			this.queue.push(animObject);
			if(!this.queueInterval) this.queueInterval = window.setInterval("getAnimationManager().animationQueue()", this.getIntervalValue());
		}
	}
	
	this.animationQueue = function() {
		for(var i=0; i < this.queue.length; i++) {
			if(!this.queue[i].animate()) {
				this.removeFromQueue(this.queue[i].id)
				i--;
			}
		}
		
		if(this.queue.length == 0) {
			clearInterval(this.queueInterval);
			this.queueInterval = null;
		}
	}
	
	this.removeFromQueue = function(objectId) {
		//this.removeObject(objectId);
		for(var i=0; i<this.queue.length; i++) {
			if(this.queue[i].id == objectId) {
				delete this.queue[i];
				if(this.queue.length > 1) {
					this.queue = this.queue.slice(0, i).concat(this.queue.slice(i+1, this.queue.length));
				} else {
					this.queue = this.queue.slice(0, 0);
				}
			}
		}
	}
	
	this.findObject = function(object) {
		for(var i=0; i < this.objectsArray.length; i++) {
			if(this.objectsArray[i])
			if(this.objectsArray[i].object == object) {
				return this.objectsArray[i];
			}
		}
		
		return null;
	}
	
	this.getObjectById = function(objectId) {
		for(var i=0; i < this.objectsArray.length; i++) {
			if(this.objectsArray[i])
			if(this.objectsArray[i].id == objectId) {
				return this.objectsArray[i];
			}
		}
		
		return false;
	}
	
	this.removeObject = function(objectId) {
		for(var i=0; i < this.objectsArray.length; i++) {
			if(this.objectsArray[i])
			if(this.objectsArray[i].id == objectId) {
				this.objectsArray[i] = null;
			}
		}
	}
	
	this.getIntervalValue = function() {
		return Math.ceil(1000/this.framePerSecond);
	}
	
	this.getControlObject = function(animObjectId) {
		var controlObject = new AnimationControlObject(animObjectId);
		return controlObject;
	}
}






var animationManagerInctanse = null;

function getAnimationManager() {
	if(animationManagerInctanse == null) {
		animationManagerInctanse = new AnimationManager();
	}
	
	return animationManagerInctanse;
}