/*
 * 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 
 */
function Effect_Slide() {
	this.element;
	this.speed = 10;
	this.step = 4;
	this.stepPercentage = true;
	
	this.totalHeight = 0;
	this.show = function() {
		this.totalHeight = this.element.position().height;
		this.element.style.display = 'block';
		
		this.element.style.height = '0px';
		this.element.style.overflow = 'hidden';
		
		var self = this;
		var height = 0;
		

		var slide = function() {
			
			if (self.stepPercentage) height += Math.round((self.totalHeight/100)*self.step);
			else height += self.step;
			self.element.apply(function() {
				this.style.height = height + 'px';
				this.scrollTop = this.scrollHeight;
				
				if (this.scrollTop > 0) setTimeout(slide, self.speed);
				else {
					this.style.height = 'auto';
				}
			});
		}		
		slide();	
	}
		
	this.hide = function() {
		var self = this;
		this.totalHeight = this.element.position().height;
		var height = this.element.position().height;
		
		
		var slide = function() {
			if (self.stepPercentage) height -= Math.round((self.totalHeight/100)*self.step);
			else height -= self.step;
			
			if (height > 0) self.element.style.height = height + 'px';
			self.element.scrollTop = self.element.scrollHeight;
			
			if (height < 1) {
				self.element.style.height = 'auto';
				self.element.style.display = 'none';
			}
			
			if (self.element.offsetHeight > 0) setTimeout(slide, this.speed);
			
		}		
		slide();
	}
}



function Effect_Fade() {
	this.element;
	this.speed = 15;
	this.step = 1;
	this.opacity = 0;
	this.oncomplete = function() {};
	
	this.show = function() {
		if (!this.element) {
			this.oncomplete();
			return;
		}
		this.opacity = 0;
		this.element.setOpacity(0);
		var self = this;
		var fade = function() {
			if (self.opacity < 100) {
				self.opacity += self.step;
				self.element.setOpacity(self.opacity/100);
				setTimeout(fade, self.speed)
			}
			else self.oncomplete();
		}
		
		fade();
		
	}
	
	this.hide = function() {
		this.opacity = 100;
		var self = this;
		var fade = function() {
			if (self.opacity > 0) {
				self.opacity -= self.step;
				self.element.setOpacity(self.opacity/100);
				setTimeout(fade, self.speed)
			}
			else self.oncomplete();
		}
		
		fade();		
	}
}

$.elementPrototype.fade = function(args) {
	var effect = new Effect_Fade();
	effect.element = this;
	
	for (var i in args) {
		effect[i] = args[i];
	}
	
	if (args.type == 'show') effect.show();
	else if (args.type == 'hide') effect.hide();
	
}


$.addElementPrototype('slide', function(args) {
	var effect = new Effect_Slide();
	effect.element = this;
	
	for (var i in args) {
		effect[i] = args[i];
	}
	
    
	if (args.type == 'show') effect.show();
	else if (args.type == 'hide') effect.hide();
	
});

$.addElementPrototype('setOpacity', function(num) {
	this.style.opacity = num;
	this.style.filter = 'alpha(opacity=' + (num*100) + ')';
});

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);
	}
}


$.addElementPrototype('toggle', function(args) {
	if (this.offsetHeight == 0) var method = 'show';
	else var method = 'hide';
	
	this[args.type]({type: method});
	
});


