var Shows = {
		current: null,
		all: {},
		onhashchange: function(e) {
			for (var i in Shows.all) {
				var s = Shows.all[i];				
				var idx = s.getHashIdx();
				if (idx > -1 && idx != s.currentidx) {
					s.showSlide(idx);
				}
			}
		}
}
window.addEventListener("hashchange", Shows.onhashchange, false);

function AudioTimer(audio, callback) {
	this.audio = audio;
	this.audio.addEventListener('timeupdate', callback, false);
}
AudioTimer.prototype.now = function() {
	return this.audio.currentTime;
}
AudioTimer.prototype.set = function(tstamp) {
	this.audio.currentTime = tstamp;
}
AudioTimer.prototype.stop = function() {
	this.audio.pause();
}
AudioTimer.prototype.start = function() {
	this.audio.play();
}

function FakeTimer(callback) {
	this._ct = 0;
	this._t = null;
	this._cb = callback;
}
FakeTimer.prototype.now = function() {
	return this._ct;
}
FakeTimer.prototype.set = function(tstamp) {
	this._ct = tstamp;
}
FakeTimer.prototype.start = function() {
	var me = this;
	this._t = setInterval(function() {me._ct += .250;me._cb()}, 250);
}
FakeTimer.prototype.stop = function() {
	clearInterval(this._t);
}
function SS(containerId, opts) {
	this.container = document.getElementById(containerId);
	this.id = containerId;
	this.playing = false;
	this.slides = [];
	this.currentidx = 0;
	this.end = 0;
	this.layers = [];
	this.currlayer = 0;
	this.nextImg = new Image();
	this.hasPlayed = false;
	opts = opts || {};
	this.show_class = 'ss_slide ' + (opts.show_class || 'show');
	this.hide_class = 'ss_slide ' + (opts.hide_class || 'hide');
	this._t = null;
}
SS.prototype.load = function(data) {
	Shows.all[this.id] = this;
	Shows.current = this;
	
	this.container.innerHTML = '<div class="ss_slides">' + 
		'<img class="ss_empty" src="img/empty.gif" style="position:absolute;top:0;left:0" />' +
		'<div class="' + this.hide_class + '" style="position:absolute;top:0;left:0"><img src=""/><div></div></div>' + 
		'<div class="' + this.hide_class + '" style="position:absolute;top:0;left:0"><img src=""/><div></div></div>' +
		'</div>' +
		'<div class="ss_nav">' +
		'<div class="prev arrows" title="type p for previous">&larr;</div>' +
		'<div class="ss_caption" style="display:none"></div>' +
		'<div class="next arrows" title="type n for next">&rarr;</div>' +
		'</div>' +
		'<button class="ss_play" title="play/pause">&rsaquo;</button>'+
		'<div class="ss_counter"></div>';
	this.slides = data.slides.sort(function(a,b) { return a.t - b.t});
	this.end = this.slides.length;
	this.layers = getElementsByClassName('ss_slide', null, this.container);
	this.empty = getElementsByClassName('ss_empty', null, this.container)[0];

	var me = this;
	
	var nav = getElementsByClassName('ss_nav', null, this.container)[0];
	var show_next;
	getElementsByClassName('prev arrows', null, nav)[0].onclick = function(){me.showPrev()};
	getElementsByClassName('next arrows', null, nav)[0].onclick = show_next = function(){me.showNext()};
	
	var imgs = this.container.getElementsByTagName('img');
	var loader = function(){this.parentNode.className = me.show_class;};
	for (var i = 0; i < imgs.length; i++) {
		if (imgs[i].className != "ss_empty") {
			imgs[i].onload = loader;
		}
		imgs[i].onclick = show_next;
	}
	this.caption = getElementsByClassName('ss_caption', null, this.container)[0];
	var tupdate = function() {me.timeupdate()};
	if (data.audio) {
		this.audio = new Audio();
		this.audio.src = data.audio;
		this.audio.load();
		this.audio.addEventListener('ended', function() {me.reset()}, false);
		this._t = new AudioTimer(this.audio, tupdate);
	} else {
		this._t = new FakeTimer(tupdate);
	}
	
	var idx = this.getHashIdx();
	this.showSlide(idx == -1 ? 0 : idx);
	getElementsByClassName('ss_play', null, this.container)[0].onclick = function() {me.playpause()};
}
SS.prototype.reset = function() {
	this._t.stop();
	this._t.set(0);
	
	this.showSlide(0);
	this.playing = false;
	this.setButton('&rsaquo;');
}
SS.prototype.setButton = function(text) {
	getElementsByClassName('ss_play', null, this.container)[0].innerHTML = text;
}
SS.prototype.playpause = function() {
	if (!this.hasPlayed) {
		// first time through, start from the beginning
		this.reset();
		this.hasPlayed = true;
	} else if (!this.playing) {
		// seek to the right point.
		this._t.set(this.slides[this.currentidx].t);
	}
	if (this.playing) {
		this._t.stop();
		this.setButton('&rsaquo;');
		this.toggleArrows(true);
	} else {
		this._t.start();
		this.setButton('||');
		this.toggleArrows(false);
	}
	this.playing = !this.playing;
}
SS.prototype.toggleArrows = function(onoff) {
	var arrows = getElementsByClassName('arrows', null, this.container);
	var opacity = onoff ? '1' : '.2';
	for (var i = 0; i < arrows.length; i++) {
		arrows[i].style.opacity = opacity;
	}
}
SS.prototype.timeupdate = function() {
	var curr = this.slides[this.currentidx + 1];
	if (curr) {
		if (this._t.now() >= curr.t) {
			this.showSlide(this.currentidx + 1);
		}
	} else {
		this.playpause();
		var me = this;
		setTimeout(function(){me.reset()}, 3000);
	}
}
SS.prototype.showSlide = function(idx) {
	var slide = this.slides[idx];
	var next_layer = this.currlayer ? 0 : 1;
    var current = this.layers[this.currlayer];
    var next = this.layers[next_layer];
	var the_img = next.getElementsByTagName('img')[0];
	current.className = this.hide_class;
	
	if (slide.src) {
		the_img.src = slide.src;
		the_img.style.display = '';
		
		this.caption.innerHTML = slide.caption;
		this.caption.style.display = '';
		next.getElementsByTagName('div')[0].style.display = 'none';
		if (the_img.complete) {
			next.className = this.show_class;
		}
		this.empty.style.display = '';
	} else {
		var d = next.getElementsByTagName('div')[0];
		d.innerHTML = slide.text;
		d.style.display = '';
		next.getElementsByTagName('img')[0].style.display = 'none';
		this.caption.style.display = 'none';
		next.className = this.show_class;
		this.empty.style.display = 'none';
	}

	window.location.hash = slide.title;
	
	this.currlayer = next_layer;
	this.currentidx = idx;
	getElementsByClassName('ss_counter', null, this.container)[0].innerHTML = ((1 + this.currentidx) + " of " + this.end);
	
	var next_slide = this.slides[idx + 1];
	if (next_slide && next_slide.src) {
		this.nextImg.src = next_slide.src;
	}
}
SS.prototype.showNext = function() {
	var n = this.currentidx + 1;
	if (n == this.end) {
		n = 0;
	}
	this.showSlide(n);
	Shows.current = this;
},
SS.prototype.showPrev = function() {
	var n = this.currentidx - 1;
	if (n < 0) {
		n = this.end - 1;
	}
	this.showSlide(n);
	Shows.current = this;
}
SS.prototype.indexForName = function(imagename) {
	for (var i = 0; i < this.slides.length; i++) {
		var slide = this.slides[i];
		if (slide.title == imagename) {
			return i;
		}
	}
	return 0;
}
SS.prototype.getHashIdx = function() {
	var hash = decodeURIComponent(window.location.hash.substr(1));
	if (hash) {
		return this.indexForName(hash);
	} else {
		return -1;
	}
}




/*
	Developed by Robert Nyman, http://www.robertnyman.com
	Code/licensing: http://code.google.com/p/getelementsbyclassname/
*/
var getElementsByClassName = function (className, tag, elm){
	if (document.getElementsByClassName) {
		getElementsByClassName = function (className, tag, elm) {
			elm = elm || document;
			var elements = elm.getElementsByClassName(className),
				nodeName = (tag)? new RegExp("\\b" + tag + "\\b", "i") : null,
				returnElements = [],
				current;
			for(var i=0, il=elements.length; i<il; i+=1){
				current = elements[i];
				if(!nodeName || nodeName.test(current.nodeName)) {
					returnElements.push(current);
				}
			}
			return returnElements;
		};
	}
	else if (document.evaluate) {
		getElementsByClassName = function (className, tag, elm) {
			tag = tag || "*";
			elm = elm || document;
			var classes = className.split(" "),
				classesToCheck = "",
				xhtmlNamespace = "http://www.w3.org/1999/xhtml",
				namespaceResolver = (document.documentElement.namespaceURI === xhtmlNamespace)? xhtmlNamespace : null,
				returnElements = [],
				elements,
				node;
			for(var j=0, jl=classes.length; j<jl; j+=1){
				classesToCheck += "[contains(concat(' ', @class, ' '), ' " + classes[j] + " ')]";
			}
			try	{
				elements = document.evaluate(".//" + tag + classesToCheck, elm, namespaceResolver, 0, null);
			}
			catch (e) {
				elements = document.evaluate(".//" + tag + classesToCheck, elm, null, 0, null);
			}
			while ((node = elements.iterateNext())) {
				returnElements.push(node);
			}
			return returnElements;
		};
	}
	else {
		getElementsByClassName = function (className, tag, elm) {
			tag = tag || "*";
			elm = elm || document;
			var classes = className.split(" "),
				classesToCheck = [],
				elements = (tag === "*" && elm.all)? elm.all : elm.getElementsByTagName(tag),
				current,
				returnElements = [],
				match;
			for(var k=0, kl=classes.length; k<kl; k+=1){
				classesToCheck.push(new RegExp("(^|\\s)" + classes[k] + "(\\s|$)"));
			}
			for(var l=0, ll=elements.length; l<ll; l+=1){
				current = elements[l];
				match = false;
				for(var m=0, ml=classesToCheck.length; m<ml; m+=1){
					match = classesToCheck[m].test(current.className);
					if (!match) {
						break;
					}
				}
				if (match) {
					returnElements.push(current);
				}
			}
			return returnElements;
		};
	}
	return getElementsByClassName(className, tag, elm);
};
