/*
 * Effect Manager, binds an effect to an element.
 * WIP:
 * Slide, Fade
 */
function ElementEffect(effect) {
	this.effect = effect;

	this.run = function(element) {
		this.effect.element = element;
		
		if (this.effect.element.computedStyle().display == 'none') method = 'show';
		else method = 'hide';
		
		this.effect[method]();
	}	
}

/*
 * Slide Effect (C) Redsky 2009 
 */


$.addElementPrototype('toggle', function(args) {
	if (this.offsetHeight == 0) var method = 'show';
	else var method = 'hide';
	
	this[args.type]({type: method});
	
});

function Effect_Slide() {
	this.element;
	this.speed = 10;
	this.step = 4;	
	
	this.show = function() {
		this.element.slideState = 'shown';
		this.element.style.display = 'block';
		this.element.style.height = '0px';
		this.element.style.overflow = 'hidden';
		
		var self = this;
		var height = 0;
		
		var slide = function() {
			height += self.step;
			self.element.style.height = height + 'px';
			self.element.scrollTop = self.element.scrollHeight;
			
			if (self.element.scrollTop > 0) setTimeout(slide, this.speed);
			else {
				self.element.style.height = 'auto';
			}
		
		}		
		slide();	
	}
		
	this.hide = function() {
		var self = this;
		this.element.slideState = 'hidden';
		var height = this.element.offsetHeight;
		this.element.style.overflow = 'hidden';
		
		var slide = function() {
			height -= self.step;
			
			if (height > 0) self.element.style.height = height + 'px';
			self.element.scrollTop = self.element.scrollHeight;
			
			if (height < 1) self.element.style.display = 'none';
			
			if (self.element.offsetHeight > 0) setTimeout(slide, this.speed);
		}		
		slide();
	}
}
 

$.elementPrototype.slide = function(args) {

	if (!args) args = {};
	var effect = new Effect_Slide();
	effect.element = this;
	
	for (var i in args) {
		effect[i] = args[i];
	}
	
	if (!args.type && this.computedStyle().display == 'none') args.type = 'show';
	else if (!args.type && this.computedStyle().display != 'none') args.type = 'hide';

	if (!this.slideState) {
		//If it's visible
		if (this.offsetHeight > 0) this.slideState = 'shown';
		else this.slideState = 'hidden';
	}

	
	if (args.type == 'show' && this.slideState == 'hidden') effect.show();
	else if (args.type == 'hide' && this.slideState == 'shown') effect.hide();
	
}



 
function Effect_Fade() {
	this.element;
	this.speed = 30;
	this.step = 6;
	this.opacity = 0;
	this.oncomplete = function() {};
	
	this.show = function() {
		
		
		
		if (this.element.fading) return;

		
		
		this.opacity = 0;
		this.element.style.opacity = 0;
		var self = this;
		
		var fade = function() {
		
			self.element.fading = true;
			if (self.opacity < 100) {
				self.opacity += self.step;
				self.element.setOpacity(self.opacity/100);
				setTimeout(fade, self.speed);
				
			}
			else {
				self.element.fading = false;
				self.oncomplete();
			}
		}
		
		fade();
	}
	
	this.hide = function() {
		if (this.element.fading) return;
		
		this.opacity = 100;
		var self = this;
		var fade = function() {			
			self.element.fading = true;
			if (self.opacity > 0) {
				self.opacity -= self.step;
				self.element.style.opacity = (self.opacity/100);
				setTimeout(fade, self.speed)
			}
			else {
				self.element.fading = false;
				self.oncomplete();
			}
		}
		
		fade();		
	}
}

$.elementPrototype.fade = function(args) {
	if (!args) args = {};
	var effect = new Effect_Fade();
	effect.element = this;
	
	for (var i in args) {
		effect[i] = args[i];
	}
	
	if (!args.type) args.type = 'show';
	
	if (args.type == 'show') effect.show();
	else if (args.type == 'hide') effect.hide();
	
}

function Effect_FadeCycle(elements) {
	this.index = 0;
	this.interval = 10000;
	
	this.elements = elements;
	this.elements.item(0).style.display = 'block';	

	this.run = function() {
		var self = this;
		this.elements.item(this.index).fade({type: 'hide', speed: 25, step: 1, oncomplete: function(){ self.next(); } });
	}
	
	this.start = function() {
		var self = this;
		setTimeout(function() { self.run(); }, this.interval);
	}
	
	this.next = function() {
		this.elements.item(this.index).style.display = 'none';
		this.index++
		if (!this.elements.item(this.index)) this.index = 0;
		
		
		this.elements.item(this.index).fade({type: 'show', speed: 25, step: 1});
		this.elements.item(this.index).style.display = 'block';
		var self = this;
		setTimeout(function() { self.run(); }, this.interval);
	}
}


function Effect_Move(element) {
	this.element = element;
	this.step = 5;
	this.speed = 20;
	
	this.slide = function(direction, amount) {

		var origMargin = parseInt(this.element.style.marginLeft.split('px')[0]);
		if (isNaN(origMargin)) origMargin = 0;
		
		if (direction == -1 && origMargin == 0) {
			this.element.moving = false;
			return;
		}
		var pos = this.element.position();
		
		//console.log((Math.abs(origMargin) + direction )+ ' ' + (pos.width - amount))
		if ((Math.abs(origMargin) + direction) >= (pos.width - amount)){
			this.element.moving = false;
			return;
		}
		
		
		
		var self = this;
		var slide = function() {
			if (Math.abs(self.element.style.marginLeft.split('px')[0]) != Math.abs(Math.abs(origMargin) + (direction*amount))) {
				self.element.style.marginLeft = (self.element.style.marginLeft.split('px')[0] - (direction*self.step)) + 'px';
				//console.log(self.element.style.marginLeft);
				setTimeout(slide, self.speed);				
			}
			else { 
								self.element.moving = false;

								}
		}
		this.element.moving = true;
		slide();		
	}
	
	this.translate = function(x, y, timeout) {
		
	}
}

$.elementPrototype.move = function(args) {
	if (!this.moving || (args.allowStacking)) {
		var effect = new Effect_Move(this);
		effect.slide(args.direction, args.amount);
	}
}

$.elementPrototype.setOpacity = function(num) {
	this.style.opacity = num;
	this.style.filter = 'alpha(opacity=' + (num*100) + ')';
}

