/******************************************************
	Index:
	  
	1) Engine
		1.0) Init
		1.1) Start
		1.2) Perform
	
	
	2) Applications
	
		2A) Toggle Show/Hide Animated
			2A.1) Main
			2A.2) Hide Animated
			2A.3) Show Animated
			
		2B) Fade In/Fade Out
		
******************************************************/


/* --------------------------------------------------------------------------------------------- */
/* 1) Engine
/* --------------------------------------------------------------------------------------------- */

// 1.0) Init
// .......................................................................
	var animation = {
		timer: new Array(),
		params: new Array(),
		start: new Array(),
		animtick: new Array(),
		animend: new Array(),
		length: new Array()
	};

// 1.1) Start
// .......................................................................
	animation.start = function(name, params, length, onanimtick, onanimend) {
		if(animation.timer[name])
			return;
	
		animation.params[name] = params;
		animation.start[name] = (new Date()).getTime();
		animation.length[name] = length;
		animation.animtick[name] = onanimtick;
		animation.animend[name] = onanimend;
	
		animation.timer[name] = setInterval('animation.perform(\'' + name + '\');', 5);
	}

// 1.2) Perform
// .......................................................................
	animation.perform = function(name) {
		var elapsed = (new Date()).getTime() - animation.start[name];
	
		if(elapsed > animation.length[name]) {
			clearInterval(animation.timer[name]);
	
			var params = animation.params[name];
			var length = animation.length[name];
			var animend = animation.animend[name];
	
			delete(animation.timer[name]);
			delete(animation.params[name]);
			delete(animation.start[name]);
			delete(animation.animtick[name]);
			delete(animation.animend[name]);
			delete(animation.length[name]);
	
			animend(elapsed, length, params);
	
			return;
		}
	
		animation.animtick[name](elapsed, animation.length[name], animation.params[name]);
	
		return;
	}


/* --------------------------------------------------------------------------------------------- */
/* 2) Applications
/* --------------------------------------------------------------------------------------------- */

	var animate = {};


/* --------------------------------------------------------------------------------------------- */
/* 2A) Toggle Show/Hide Animated
/* --------------------------------------------------------------------------------------------- */

// 2A.1) Main
// .......................................................................
	animate.toggle = function(node) {
		var n = $(node);
		
		/* Need To Display Element In Order To Get Its Height >> ... */
		var wasHidden = isHidden(node);
		show(n);
		/* ... << */
		
		var height = n.offsetHeight;
	
		/* Set Display To None Again After Getting Its Height >> ...*/
		if(wasHidden)
			hide(n);
		/* ... << */
		
		if(n.style.height == '')
			n.style.height = height + 'px';
		else
			height = parseInt(n.style.height);
	
		var params = {
			node: n,
			height: height,
			dir: 'up'
		};
		
		if(isHidden(n)) {
			params.dir = 'down';
			n.style.height = '1px';
		}
		else
			params.dir = 'up';
	
		show(n);
		n.style.overflow = 'hidden';
		
		animation.start(n.id, params, 500, animate.move, animate.stopped);
	}

	/* PRIVATE **********************************************************/
	animate.move = function(elapsed, length, params) {
		var d = elapsed / length;
	
		if(params.dir == 'up')
			d = 1 - d;
	
		params.node.style.height = Math.round(params.height * d) + 'px';
		
		if(!GLOBAL['IE6'])
			setOpacity(params.node, 100 * d);
	}
	
	animate.stopped = function(elapsed, length, params) {
		if(params.dir == 'up')
			hide(params.node);
	
		params.node.style.height = '';
		params.node.style.overflow = 'visible';
		
		// Refresh Observer
		observer.refresh();
	}
	

// 2A.2) Hide Animated
// .......................................................................
	animate.hide = function(node, action) {
		
		/* Set Node To Visible */
		var n = $(node);
		if(isHidden(n))
			return;
		
		/* Use Toggle Function: Reaction = Hiding */
		show(n);
		this.toggle(node, action);
	}


// 2A.3) Show Animated
// .......................................................................
	animate.show = function(node, action) {
		
		/* Set Node To Hidden */
		var n = $(node);
		if(!isHidden(n))
			return;
		
		/* Use Toggle Function: Reaction = Showing */
		hide(n);
		this.toggle(node, action);
	}




/* --------------------------------------------------------------------------------------------- */
/* 2B) Fade In/Fade Out
/* --------------------------------------------------------------------------------------------- */

// 2B.0) Init
// .......................................................................
	
	animate['fade_speed'] = 500;
	

// 2B.1) Fade
// .......................................................................
	
	// direction: {in, out}
	animate.fade = function(direction, node) {
	
		var params = {
			direction: direction,
			node: node
		};
		
		animation.start('fade' + Math.random(), params, this.fade_speed, this.fade_tick, this.fade_end);
	}


// 2B.3) Tick & End - PRIVATE
// .......................................................................
	animate.fade_tick = function(elapsed, length, params) {
		
		var progress = Math.round(elapsed / length * 100);
		var opacity;
		
		switch(params.direction) {
			
			case 'out':
				opacity = 100 - progress;
				break;
			
			case 'in':
				opacity = progress;
				break;
		}
			
		params.node.style.opacity = (opacity / 100.0);
		params.node.style.MozOpacity = (opacity / 100.0);
		params.node.style.filter = 'alpha(opacity = ' + opacity + ')';
	}

	animate.fade_end = function(elapsed, length, params) {
		animate.fade_tick(1, 1, params);
	}
	
