var Webadmin = window.Webadmin || {};
 
/*
	Class: Webadmin.Animation
	
	Webadmin Animation class.
	
	Parameters:
	
		{HTMLElement} element - The element to animate.
		{Object} options - The animation options.
		{Int} duration - The duration of the effec in seconds
		
	Returns:
	
		void
*/	
Webadmin.Animation = function(element, options, duration, easing){
	this.properties = {};
	this.animating=false;
	this.element = element;
	this.options = {};
	this.options._from = options.start || null;
	this.options._to = options.end || null;
	this.duration = duration||1000;
	this.interval = this.duration/10;
	this.state=0;
	this.target=0;
	this.toggle=false;
	this.easing = easing||Webadmin.Easing.linear 
	this.setup();
	this.oncomplete=new Webadmin.Event.custom.publisher();
	this.ontween=new Webadmin.Event.custom.publisher();
};

Webadmin.Animation.prototype.getValue = function(value){
	var v = parseInt(value,10);
	return v;
};

Webadmin.Animation.prototype.setup = function(){	
	var property;
	var units;
	var value;
	if(this.animating!==true){
		if(this.onstart){
			this.onstart();
		}
		if(this.toggle!==true){
			if(this.options._from!=null){
				this.options._from.split(';').filter(function(a){
					if(a!==''&&a!=null){
						return a;
					}
				}).forEach(function(rule){
					rule = rule.split(':');
					property = rule[0].trim().camelize();
					value = this.getValue(rule[1].trim());
					units = 'px';
					this.element.style[property]=value;
					this.properties[property] = this.properties[property] || {};
					this.properties[property]._from = {value: value, units: units};
				}, this);
			}else{
			}
			if(this.options._to){
				this.options._to.split(';').filter(function(a){
					if(a!==''&&a!=null){
						return a;
					}
				}).forEach(function(rule){
					rule = rule.split(':');
					property = rule[0].trim().camelize();
					/* Work this out in getUnits using a regex */
					if(property=='opacity'){
						value=rule[1].trim();
					}else{
						value = this.getValue(rule[1].trim());
					}
					units = this.getUnits(property);
					this.properties[property] = this.properties[property] || {};
					if(!this.properties[property]._from){
						var from = this.getValue(Webadmin.Dom.getStyle(this.element, rule[0].trim()));
						if(property!='opacity'){
							from = parseInt(from, 10);
						}
						this.properties[property]._from = {value: from, units: units};
						this.element.style[property]=from+units;
					}

					this.properties[property]._to = {value: value, units: units};
				}, this);	
			}
		}
	}
};

Webadmin.Animation.prototype.getUnits = function(property){
	if(property=='opacity'){
		return '';
	}else{
		return 'px';
	}
};

/* 
	Function: animate
	
	Starts the animation.
	
	Returns:
		
		void
	
*/
Webadmin.Animation.prototype.animate = function(property){
	this.target = Math.max(0, Math.min(1, 1-this.target));
	this.state = Math.max(0, Math.min(1, this.state));
	var _this = this;
	this.callback = function(){_this.step();};
	this.intval = window.setInterval(this.callback, this.interval);
};

Webadmin.Animation.prototype.step = function(){
	var property, value;
	var movement = (this.interval / this.duration) * (this.state < this.target ? 1 : -1);
	if (Math.abs(movement) >= Math.abs(this.state - this.target)) {
		this.state = this.target;
	} else {
		this.state += movement;
	}
	for(property in this.properties){
		var _from = (this.target==1) ? this.properties[property]._from : this.properties[property]._to;
		var _to = (this.target==1) ? this.properties[property]._to : this.properties[property]._from;
		var state = this.easing(this.state);
		if(property=='opacity'){
			value = parseFloat(_from.value) + ((_to.value - _from.value) * state);	
		}else{
			value=Math.round(parseInt(_from.value, 10) + ((_to.value - _from.value) * state));
		}
		Webadmin.Dom.setStyle(this.element, property, value+_to.units);
	}
	if(this.state==this.target){
		window.clearInterval(this.intval);
		this.toggle=true;
		this.intval=null;
		this.oncomplete.fire();
	}
	this.ontween.fire();
};

Webadmin.Transition = {
	makeEaseIn : function(a) {
		return function(state) {
			return Math.pow(state, a*2); 
		}
	},
	makeEaseOut : function(a) {
		return function(state) {
			return 1 - Math.pow(1 - state, a*2); 
		}
	},
	makeElastic : function(bounces) {
		return function(state) {
			state = Webadmin.Easing.easeInOut(state);
			return ((1-Math.cos(state * Math.PI * bounces)) * (1 - state)) + state; 
		};
	},
	makeBounce : function(bounces) {
		var fn = Webadmin.Transition.makeElastic(bounces);
		return function(state) {
			state = fn(state); 
			return state <= 1 ? state : 2-state;
		};
	}
}

Webadmin.Easing = {
	easeInOut : function(p){return ((-Math.cos(p*Math.PI)/2) + 0.5);},
	linear : function(x){return x;},
	easeIn: Webadmin.Transition.makeEaseIn(1.5),
	easeOut: Webadmin.Transition.makeEaseOut(1.5),
	strongEaseIn: Webadmin.Transition.makeEaseIn(2.5),
	strongEaseOut: Webadmin.Transition.makeEaseOut(2.5),	
	elastic : Webadmin.Transition.makeElastic(1),
	veryElastic : Webadmin.Transition.makeElastic(3),
	bouncy : Webadmin.Transition.makeBounce(1),
	veryBouncy : Webadmin.Transition.makeBounce(3)
};

