/*
 * Savvy.js Extension
 * Name : Savvy.Animator
 * Version: 0.1
 * Required : Savvy.Core
 * Last Updated: 29.05.2007
 * Author: Cryno Bone http://www.chronosight.net/
 ***************************************************
1. Savvy.Animator is based from Savvy.Animation with much powerful transaction feature.
*/
var Animator = function() {
	this.object 	= null;
	this.element 	= null;
	this.interval	= null;
	this.does 		= null;
	this.width 		= 0;
	this.height 	= 0;
	this.margin 	= [];
	this.top 		= 0;
	this.left 		= 0;
	this.oncomplete = null;
	this.type		= null;
	this.transaction = [];
	this.methods 	= ["moveUp", "moveDown", "moveLeft", "moveRight", "slideUp", "slideDown", "slideLeft", "slideRight", "resizeWidth", "resizeHeight", "fade", "custom"];
	this.withPx 	= ["margin", "marginTop", "marginLeft", "marginBottom", "marginRight", "padding", "paddingTop", "paddingLeft", "paddingBottom", "paddingRight", "top", "left", "right", "bottom", "width", "height"];
	this.shutter 	= 20;
	this.step		= 0;
	this.ease		= 0;
	this.actStep	= 0;
};

Animator.prototype = {
	Initialize : function(arg) {
		var element 	= Func.Grab(arg.object, arg.element);
		var object 		= new Elements;
		
		if(Func.CheckId(element)) {
			object.Id(element);
		} else {
			object.Create("div").setProperty("id", element);
		}
		
		this.object 	= object;
		this.element 	= element;
		
		return this;
	},
	Queue : function(arg) {
		var this_object = this;
		this.oncomplete = function() {
			var obj = new Animator;
			obj.Initialize({element:this.element});
			obj.Fx(arg);
		};
		
		return this;
	},
	Sync : function(arg) {
		var this_object = this;
		var obj = new Animator;
		obj.Initialize({element:this.element});
		obj.Fx(arg);
		
		return this;
	},
	Fx : function(arg) {		
		arg.method 		= (this.methods.inArray(arg.method) ? arg.method : "moveUp");
		this.does 		= arg.method;
		this.oncomplete = arg.oncomplete = pick(arg.oncomplete, null);
		this.getDimension();
		this.shutter 	= arg.shutter = pick(arg.shutter, 20);
		this.step 		= arg.step = pick(arg.step, 80);
		this.ease 		= pick(arg.ease, 0.8);
		this.actStep 	= 0;
		
		if(this.does == "moveUp" || this.does == "moveDown" || this.does == "moveLeft" || this.does == "moveRight") {
			var trans = arg.transaction;
			
			if(this.does == "moveLeft" || this.does == "moveRight") {
				this.type = pick(arg.property, "marginLeft");
				
				if(this.type != "marginLeft" && this.object.getStyle("position")) {
					this.type = "left";
					this.transaction[0] = pick(trans[0], this.left);
					this.transaction[1] = trans[1];
				} else {
					this.type = "marginLeft";
					this.transaction[0] = pick(trans[0], this.margin[3]);
					this.transaction[1] = trans[1];
				}
			} else if(this.does == "moveUp" || this.does == "moveDown") {
				this.type = pick(arg.property, "marginTop");
				if(this.type != "marginTop" && this.object.getStyle("position")) {
					this.type = "top";
					this.transaction[0] = pick(trans[0], this.top);
					this.transaction[1] = trans[1];
				} else {
					this.type = "marginTop";
					this.transaction[0] = pick(trans[0], this.margin[0]);
					this.transaction[1] = trans[1];
				}
			}
			var this_object = this;
			this.interval = setInterval(function() { this_object.Custom(); }, this.shutter);
		}
		else if(this.does == "resizeWidth" || this.does == "resizeHeight") {
			this.type 	= (arg.property, "normal");
			this.does 	= arg.property = (arg.method == "resizeWidth" ? "width" : "height");
			var trans 	= arg.transaction;
			
			if(this.does == "width") {
				this.transaction[0] = pick(trans[0], this.width);
				this.transaction[1] = trans[1];
			} else {
				this.transaction[0] = pick(trans[0], this.height);
				this.transaction[1] = trans[1];
			}
			var this_object = this;
			this.interval = setInterval(function() { this_object.Sizer() }, this.shutter);
		} else if(this.does == "fade") {
			this.type = arg.property = arg.method;
			
			var trans = arg.transaction;
		
			trans[0] = (trans[0] < 0 ? 0 : (trans[0] > 100 ? 100 : trans[0]));
			trans[1] = (trans[1] < 0 ? 0 : (trans[1] > 100 ? 100 : trans[1]));
			this.transaction[0] = trans[0];
			this.transaction[1] = trans[1];
			
			var this_object = this;
			this.interval = setInterval(function() { this_object.Fader(); }, this.shutter);
		} else if(this.does == "custom") {
			this.type = arg.property;
			var trans = arg.transaction;
			this.transaction[0] = trans[0];
			this.transaction[1] = trans[1];
			
			var this_object = this;
			this.interval = setInterval(function() { this_object.Custom(); }, this.shutter);
		}
		
		return this;
	},
	End : function() {
		return this;
	},
	Fader: function() {
		var object = this.object.getElement();
		if(!is_null(object)) {
			var trans 		= this.transaction;
			this.actStep 	= (this.actStep + 1);
			var step 		= this.easeInOut(trans[0], trans[1], this.step, this.actStep, this.ease);
			if(trans[0] != trans[1]) { 
				try {
					if(step == 0 && CSS.Get(object, "visibility") != "hidden") { 
						CSS.Hide(object);
					} else if(step > 0 && CSS.Get(object, "visibility") == "hidden") {
						CSS.Show(object);
					}
					
					if (window.ActiveXObject || Savvy.browser.ie == true) {
						if (!object.currentStyle || !object.currentStyle.hasLayout) {
							CSS.Set(object, "zoom", 1);
						}
						CSS.Set(object, "filter", (step < 100 ? "alpha(opacity=" + step + ")" : ""));
					} else {
						CSS.Set(object, "opacity", (step / 100));
						CSS.Set(object, "MozOpacity", (step / 100));
					}
				} catch(e) {  }
				this.transaction[0] = step;
			} else {
				var fn = this.oncomplete;
				if(fn != null && typeof(fn) == "function") {
					Func.Callback(this, fn);
				}
					
				clearInterval(this.interval);
				this.interval = null;
				this.End();
			}
		}
		return this;
	},
	Sizer: function() {
		var object 	= this.object.getElement();
		var a 		= this.does;
		
		var opt	 	= ["width", "height"];
		var type	= this.type;
		
		if(opt.inArray(a)) {
			var trans 		= this.transaction;
			this.actStep 	= (this.actStep + 1);
			var step 		= this.easeInOut(trans[0], trans[1], this.step, this.actStep, this.ease);
			
			if(trans[0] != trans[1]) { 
				if(this.withPx.inArray(a)) {
					CSS.Set(object, a, step + "px");
				} else {
					CSS.Set(object, a, step);
				}
				
				if(type == "center" && CSS.Get(object, "position")) {
					if(a == "height") {
						var oTop 	= CSS.Get(object, "top").toNumber();
						var fTop 	= (oTop - (step / 2));
						CSS.Set(object, "top", fTop);
					} else {
						var oLeft 	= CSS.Get(object, "left").toNumber();
						var fLeft 	= (oLeft - (step / 2));
						CSS.Set(object, "left", fLeft);
					}
				}
				
				this.transaction 	= [step, trans[1]];
			} else {
				var fn = this.oncomplete;
				if(fn != null && typeof(fn) == "function") {
					Func.Callback(this, fn);
				}
				
				clearInterval(this.interval);
				this.interval = null;
				this.End();
			}
		} else {
			clearInterval(this.interval);
			this.interval = null;
			this.End();
		}
		return this;
	},
	Custom : function() {
		var object		= this.object.getElement();
		var trans 		= this.transaction;
		var type 		= this.type;
		this.actStep 	= (this.actStep + 1);
		var step 		= this.easeInOut(trans[0], trans[1], this.step, this.actStep, this.ease);
		
		if(trans[0] != trans[1]) { 
			if(this.withPx.inArray(type)) {
				CSS.Set(object, type, step + "px");
			} else {
				CSS.Set(object, type, step);
			}
			
			this.transaction[0]	 = step;
		} else {
			var fn = this.oncomplete;
			if(fn != null && typeof(fn) == "function") {
				Func.Callback(this, fn);
			}
			
			clearInterval(this.interval);
			this.interval = null;
		}
		return this;
	},
	easeInOut: function(minval, maxval, total, actual, powr) {
		var delta = maxval - minval;
		var stepp = minval + (Math.pow(((1 / total) * actual), powr) * delta);
		
		return Math.ceil(stepp); 
    },
	getDimension : function() {
		var obj = this.object.getElement();
		
		if(CSS.Get(obj, "position")) {
			this.top 	= pick(CSS.Get(obj, "top").toNumber(), 0);
			this.left	= pick(CSS.Get(obj, "left").toNumber(), 0);
		}
		
		this.width 		= pick(CSS.Get(obj, "width").toNumber(), obj.offsetWidth);
		this.height	 	= pick(CSS.Get(obj, "height").toNumber(), obj.offsetHeight);
		
		var marTop 		= pick(CSS.Get(obj, "marginTop").toNumber(), 0);
		var marBottom 	= pick(CSS.Get(obj, "marginBottom").toNumber(), 0);
		var marLeft 	= pick(CSS.Get(obj, "marginLeft").toNumber(), 0);
		var marRight 	= pick(CSS.Get(obj, "marginRight").toNumber(), 0);
		var margins 	= pick(CSS.Get(obj, "margin").split(" "), []);
		
		//margin:top right bottom left;
		margins[0] = margins[0].toNumber();
		margins[1] = (!is_null(margins[1]) || !isNaN(margins[1]) ? margins[1].toNumber() : margins[0]);
		margins[2] = (!is_null(margins[2]) || !isNaN(margins[2]) ? margins[2].toNumber() : margins[0]);
		margins[3] = (!is_null(margins[3]) || !isNaN(margins[3]) ? margins[3].toNumber() : margins[1]);
		
		var marginTop 		= (is_null(marTop) || isNaN(marTop) ? 0 : marTop);
		marginTop 			= (is_null(margins[0]) || isNaN(margins[0]) ? marginTop : margins[0]);
		
		var marginBottom 	= (is_null(marBottom) || isNaN(marBottom) ? 0 : marBottom);
		marginBottom 		= (is_null(margins[2]) || isNaN(margins[2]) ? marginBottom : margins[2]);
		
		var marginLeft 		= (is_null(marLeft) || isNaN(marLeft) ? 0 : marLeft);
		marginLeft 			= (is_null(margins[3]) || isNaN(margins[3]) ? marginLeft : margins[3]);
		
		var marginRight 	= (is_null(marRight) || isNaN(marRight) ? 0 : marRight);
		marginRight 		= (is_null(margins[1]) || isNaN(margins[1]) ? marginRight : margins[1]);
		
		this.object.setStyles([{
			"marginTop": marginTop + "px",
			"marginBottom": marginBottom + "px",
			"marginLeft": marginLeft + "px",
			"marginRight": marginRight + "px"
		}]);
		
		this.margin = [marginTop, marginRight, marginBottom, marginLeft];
		
		return this;
	}
};
