/*
 * 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 = 100;
	this.step = 6;
	
	
	this.show = function() {				
		this.element.style.display = 'block';
		this.element.style.height = '0px';
		this.element.style.overflow = 'hidden';
		//self.element.moving = true;
		
		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;
		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();
	}
}
 
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);
	}
}

var Effect_CrossFade2 = function(elements) {
	this.front = new $e('div');
	this.back = new $e('div');
	this.interval = 10000;
	this.currentImage = null;
	this.random = false;
	
	this.elements = elements;
	
	this.front.style.width = elements.item(0).position().width + 'px';
	
	this.front.style.height = elements.item(0).position().height + 'px';
	this.front.style.position = 'absolute';
	
	this.back.style.width = elements.item(0).position().width + 'px';
	this.back.style.height = elements.item(0).position().height + 'px';
	
	
	elements.item(0).parentNode.insertBefore(this.front, elements.item(0));
	elements.item(0).parentNode.insertBefore(this.back, elements.item(0));
	
	
	
	
	this.pool = new $e('div');
	
	
	
	for (var i = 0; i < elements.count(); i++) {
		this.pool.appendChild(elements.item(i));
	}
	
	//and put back item0
	//this.back.appendChild(elements.item(0));
	
	//Move front over back
	
//	this.front.style.position = 'absolute';
	//this.front.style.top = this.back.position().top + 'px';
	//this.front.style.left = this.back.position().left + 'px';
	


	this.start = function() { 
		//document.body.appendChild(this.front);
		
		//if it's random, put a random one on top in the pool
		var self = this;
		//setTimeout(function() {self.fade();}, this.interval);
		this.fade();
		self.front.appendChild(self.elements.item(self.getNextImage()));
	}
	
	
	this.fade = function() {
		var self = this;
		//var next = this.getNextImage();
		this.front.style.display = 'block';
		this.front.fade({type: 'show',
			oncomplete: function() {
				//self.backgroundDiv.style.backgroundImage = 'url(' + self.elements.item(next).src + ')';
				//
				
				//move back to pool
				for (var i = 0; i < self.back.childNodes.length; i++) self.pool.appendChild(self.back.childNodes[i]);
				
				
				//move front to back
				for (var i = 0; i < self.front.childNodes.length; i++) self.back.appendChild(self.front.childNodes[i]);
				
							
				
				//load a new image in front
				self.front.appendChild(self.elements.item(self.getNextImage()));
				
			
				self.front.style.display = 'none';
				//self.elements.item(next).style.display = 'none';	
				//
			}
		});
		
		
		setTimeout(function() {self.fade();}, 5000);
	
	}
	
	
	
	this.getNextImage = function() {
		if (this.random) {
			var i = 0;
			var rand = Math.round(Math.random()*(this.elements.count()-1));
			while (i < 100 && this.currentImage == rand ) {
				//dont get same image twice
				rand = Math.ceil(Math.random()*this.elements.count()-1);
				i++; //safetey precaution
			}
			
			this.currentImage = rand;
			return this.currentImage;
		}
		else {
			if (this.currentImage == this.elements.count()-1 || this.currentImage == null) this.currentImage = 0;
			else this.currentImage++;			
			return this.currentImage;
		}
	}
	
}

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


$.elementPrototype.transformScale = function(scale) {
	if (navigator.appName.indexOf('Explorer') > 1) {
		this.firstChild.style.zoom = scale;
	}
	else {
		this.style.MozTransform = 'matrix(' + scale + ', 0, 0, ' + scale + ', 0, 0)'; 
		this.style.WebkitTransform = 'matrix(' + scale + ', 0, 0, ' + scale + ', 0, 0)'; 
	}
}

$.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('toggle', function(args) {
	if (this.offsetHeight == 0) var method = 'show';
	else var method = 'hide';
	
	this[args.type]({type: method});
	
});
