/********
* cvhFadeStack - A thing that rotates a stack of things with fades
* (c) 2008 Chris VandenHeuvel (fastballweb.com)
* version 2.6.S (2009-03-30, edited)
* requires cvhUtils and cvhDHTML (fastballweb.com/javascripts)
* Fill a relative-pos. container div with just about anything and call function
* transparentSlides - set to true for better transparent slide transitions.
* If something in the container shouldn't be a slide, add a "nonslide" class. 
********/
if (!window.cvhDHTML) {
	var scripts = document.getElementsByTagName('script');
	for (var i = 0; i < scripts.length; i++) {
		if (scripts[i].src.indexOf('cvhfadestack') !== -1) {
			var path = scripts[i].src.replace(/cvhfadestack/, 'cvhdhtml');
			var script = document.createElement('script');
			script.type = 'text/javascript';
			script.src = path;
			document.getElementsByTagName('head')[0].appendChild(script);
			break;
		}
	}
}
function cvhFadeStack(containerId, pauseSeconds, transparentSlides, random, FPS) {
	var that = {}
	var fisherYates = function(input) { // randomize array
		for (var i = input.length - 1; i > 0; i--) {
			var j = Math.floor(Math.random() * (i + 1));
			var k = input[i];
			var l = input[j];
			input[i] = k;
			input[j] = l;
		}
	}
	var refresh = function() { // set styles according to stack position
		for (var i = 0; i < stack.length; i++) {
			var slide = stack[i];
			slide.style.zIndex = stack.length - i;
			cvhDHTML.setOpacity(slide, 100);
			opacity = 100;
			slide.style.position = 'absolute';
			if (i == 0) {
				slide.style.display = 'block';
				if (slide.activate) { slide.activate(true); }
			} else {
				slide.style.display = 'none';
				if (slide.activate) { slide.activate(false); }
			}
		}
	}
	var next = function() { // move first slide to end
		var slide = stack.shift();
		if (random) { fisherYates(stack); }
		stack.push(slide);
	}
	var setNext = function () {
		stack = [stack[0]];
		for (var i = 0, j = nextSlide; i < slides.length; i++) {
			if (slides[j] !== stack[0]) { stack.push(slides[j]); }
			j++;
			if (j == slides.length) { j = 0; }
		}
	}
	var cut = function() {
		stack = [];
		for (var i = 0, j = nextSlide; i < slides.length; i++) {
			stack.push(slides[j]);
			j++;
			if (j == slides.length) { j = 0; }
		}
	}
	var fade = function() { // execute visual fade, then run queued function 
		if (opacity > 0) {
			if (opacity == 100) {
				if (transparentSlides) { cvhDHTML.setOpacity(stack[1], 0); }
				stack[1].style.display = 'block';
			}
			opacity -= 5;
			if (opacity < 0) { opacity = 0; }
			cvhDHTML.setOpacity(stack[0], opacity);
			if (transparentSlides) { cvhDHTML.setOpacity(stack[1], 100 - opacity); }
			timer = window.setTimeout(fade, interval);
		} else {
			timerQueue();
		}
	}
	var unfade = function() {
		if (opacity < 100) {
			opacity += 20;
			if (opacity > 100) { opacity = 100; }
			cvhDHTML.setOpacity(stack[0], opacity);
			if (transparentSlides) { cvhDHTML.setOpacity(stack[1], 100 - opacity); }
			timer = window.setTimeout(unfade, interval);
		} else {
			stack[1].style.display = 'none';
			if (transparentSlides) { cvhDHTML.setOpacity(stack[1], 100); }
			timerQueue();
		}
	}
	var advance = function() { // update positions and styles after fade
		timerQueue = function() {};
		next();
		refresh();
		that.play();
	}
	var goToIn = function() {
		container.onmouseover = function() {};
		setNext();
		refresh();
		if (stack[0] !== slides[nextSlide]) {
			timerQueue = goToOut;
			fade();
		} else {
			goToOut();
		}
	}
	var goToOut = function() {
		timerQueue = function() {
		container.onmouseover = mousein;
		};
		cut();
		refresh();
		that.play();
	}
	that.play = function() { // set stack to begin fade at appropriate time
		window.clearTimeout(timer);
		timerQueue = advance;
		if (opacity == 100) {
			timer = window.setTimeout(fade, pauseMS);
		} else {
			fade();
		}
	}
	that.pause = function() { // stop everything, fading first slide back in
		window.clearTimeout(timer);
		if (opacity < 100) {
			timerQueue = function() {};
			unfade();
		}
	}
	var mousein = function(e) {
		if (cvhUtils.checkMouseMove(e, container)) {
			that.pause();
		}
	}
	var mouseout = function(e) {
		if (cvhUtils.checkMouseMove(e, container)) {
			that.play();
		}
	}
	that.goToSlide = function(slide) {
		window.clearTimeout(timer);
		nextSlide = slide;
		if (opacity < 100) {
			timerQueue = goToIn; 
			unfade();
		} else {
			goToIn();
		}
	}
	that.forward = function() {
		window.clearTimeout(timer);
		timerQueue = advance;
		fade();
	}
	that.registerControl = function(slide, callback) {
		slides[slide].activate = callback;
		refresh();
	}
	that.autoRegister = function(controlsId, activatedClass) {
		var controls = document.getElementById(controlsId).getElementsByTagName('a');
		for (var i = 0; i < controls.length; i++) {
			(function(slide) {
				var control = controls[slide];
				var click = function() {
					that.goToSlide(slide);
					return false;
				}
				control.onclick = click;
				var activate = function(on) {
					control.className = on ? activatedClass : '';
				}
				that.registerControl(slide, activate);
			})(i);
		}
	}
	var pauseSeconds = pauseSeconds || 5;
	var pauseMS = pauseSeconds * 1000;
	var transparentSlides = transparentSlides || false;
	var random = random || false;
	var FPS = FPS || 24;
	var interval = parseInt(1000 / FPS);
	var opacity = 100;
	var timer;
	var timerQueue = function() {};
	var nextSlide = 0;
	var container = document.getElementById(containerId);
	var slides = [];
	if (container) {
		for (var i = 0; i < container.childNodes.length; i++) {
			if (container.childNodes[i].nodeType == 1 && container.childNodes[i].className.indexOf('nonslide') == -1) {
				slides.push(container.childNodes[i]);
			}
		}
		var stack = slides.slice();
		if (slides.length > 1) {
			container.style.position = 'relative';
			refresh();
			container.onmouseover = mousein;
			container.onmouseout = mouseout;
			that.play();
		}
	}
	return that;
}
