var slides, utils, buttons, keys, slideshow, audio, application;

jQuery.fn.exists = function(){ return jQuery(this).length>0; };

$(document).ready(function() {
	slideshow.prepare();
	$(".play").click(function() { 
		if ($("body").hasClass("audio_ready")) {
			slideshow.play(); 
		}
		return false;
	});
});

application = $.sammy(function() {

	this.get('#slide-:position', function() {
		slides.reveal(this.params['position']);
		audio.scrubToCurrentSlidePosition();
		if (this.params['position'] === '21') {
			slideshow.pause();
		}
	});

});


slideshow = {
	prepare: function() {
		$("body").addClass("scripted");
		audio.setup( slideshow.setup, slideshow.activate );
	},

	setup: function() {
		$("body").addClass("audio_loading");
		buttons.setup();
		keys.setup();
	},

	activate: function() {
		slides.hideAll();
		$("body").removeClass("audio_loading").addClass("audio_ready");
		application.run();
		if (slides.current.number() === 0) {
			slideshow.showIntro();
		}
	},

	showIntro: function() {
		$("#slide-00").show();
	},

	toggle: function() {
		if (slideshow.isPlaying()) {
			slideshow.pause();
		}
		else {
			slideshow.play();
		}
	},

	play: function() {
		if (slides.current.number() === 21) {
			slides.first();
		}
		audio.play();
		buttons.toggle_play.text("Pause");
	},
	pause: function() {
		audio.pause();
		buttons.toggle_play.text("Play");
	},

	isPlaying: function() {
		return( buttons.toggle_play.text() !== "Play" );
	},

	advance: function() {
		slides.advance();
	},
	reverse: function() {
		slides.reverse();
	}
};

audio = {
	element: "",
	ogg_src: "http://allsorts.s3.amazonaws.com/pechakucha.ogg", // audio/ogg
	aac_src: "http://allsorts.s3.amazonaws.com/pechakucha.m4a", // audio/mp4 or audio/x-m4a
	mp3_src: "http://allsorts.s3.amazonaws.com/pechakucha.mp3", // audio/mpeg

	setup: function(audioSupportedCallback, audioReadyCallback) {
		audio.element = document.createElement('audio');
		audio.element.src = audio.getSupportedAudioFormat();
		if( $(audio.element).attr("src") === "" ) {
			console.log("None of the specified audio formats are supported");
			$("body").addClass("no-audio-support");
		} else {
			audio.element.controls = false;
			audio.element.addEventListener('timeupdate', audio.updateTimeLine, false);
			audio.element.addEventListener('ended', audio.resetTimeLine, false);
			if (typeof audioSupportedCallback === 'function') {
				audioSupportedCallback();
			}
			if (typeof audioReadyCallback === 'function') {
				audio.element.addEventListener('loadeddata', audioReadyCallback, false);
			}
			//audio.element.addEventListener('canplaythrough', audio.initializeTimeLine, false);
			document.body.appendChild(audio.element);
		}
	},

	play: function() {
		//audio.element.muted = true;
		audio.element.play();
	},

	pause: function() {
		audio.element.pause();
	},

	scrubToCurrentSlidePosition: function() {
		audio.element.currentTime = slides.current.startAt();
	},

	resetTimeLine: function() {
		alert("ended!");
		audio.element.currentTime = 0;
	},

	initializeTimeLine: function() {
		if ( audio.element.currentTime < slides.current.startAt() ) {
			audio.scrubToCurrentSlidePosition();
		}
	},

	updateTimeLine: function() {
		if ( audio.element.currentTime > slides.current.finishAt() ) {
			slides.advance();
		}
		$("#nav li a").removeClass("current")
			.removeClass("completed")
			.css('background-position', '0% 0%');

		slides.previous.navItems().addClass("completed");

		var correction_factor = 1.1,
			progress = slides.current.progress( audio.element.currentTime );

		slides.current.navItem()
			.css('background-position', "0% -" + (progress * correction_factor) + "%")
			.addClass("current");
	},

	html5AudioSupported: function() {
		return !!document.createElement('audio').canPlayType;
	},

	getSupportedAudioFormat: function() {
		//return "";
		//return "/audio/pechakucha.ogg";
		if( audio.aacSupported() )         { return audio.aac_src; }
		else if( audio.vorbisSupported() ) { return audio.ogg_src; }
		else if( audio.mp3Supported() )    { return audio.mp3_src; }
		else                               { return ""; }
	},

	vorbisSupported: function() {
		return !!(audio.element.canPlayType && audio.element.canPlayType('audio/ogg; codecs="vorbis"').replace(/no/, ''));
	},

	mp3Supported: function() {
		return !!(audio.element.canPlayType && audio.element.canPlayType('audio/mpeg;').replace(/no/, ''));
	},

	aacSupported: function() {
		return !!(audio.element.canPlayType && audio.element.canPlayType('audio/mp4; codecs="mp4a.40.2"').replace(/no/, ''));
	},

	wavSupported: function() {
		return !!(audio.element.canPlayType && audio.element.canPlayType('audio/wav; codecs="1"').replace(/no/, ''));
	}
};

keys = {
	space: 32,
	left_arrow: 37,
	up_arrow: 38,
	right_arrow: 39,
	down_arrow: 40,

	setup: function() {
		$(document).keydown(function(event) {
			if( event.keyCode === keys.space )       { slideshow.toggle(); return false; }
			if( event.keyCode === keys.left_arrow )  { slideshow.reverse(); return false; }
			if( event.keyCode === keys.up_arrow )    { slideshow.reverse(); return false; }
			if( event.keyCode === keys.right_arrow ) { slideshow.advance(); return false; }
			if( event.keyCode === keys.down_arrow )  { slideshow.advance(); return false; }
		});
	}
};

buttons = {
	toggle_play: "",

	setup: function() {
		if ($("#pButton").exists()) {
			$("#pButton").remove();
		}
		$("#nav").prepend("<a href='#' id='pButton'>Play</a>");
		buttons.toggle_play = $("#pButton");
		buttons.toggle_play.click( function() {
			if ($("body").hasClass("audio_ready")) {
				slideshow.toggle();
			}
			return false;
		});
	}
};

slides = {
	durationPerSlide: 20,

	count: function() {
		return $("#slideshow>li").size();
	},

	hideAll: function() {
		$("#slideshow>li").hide();
	},

	reveal: function(position) {
		slides.hideAll();
		position = utils.zeroPadNumber(position);
		$('#slide-' + position).show();
	},

	first: function() {
		$(window.location).attr('hash', '#slide-01');
	},

	advance: function() {
		var targetHash,
			nextNumber = slides.next.number();

		if (nextNumber < slides.count()) {
			targetHash = "#slide-" + utils.zeroPadNumber(nextNumber);
			$(window.location).attr('hash', targetHash);
		}
	},

	reverse: function() {
		var targetHash,
			previousNumber = slides.previous.number();

		if (previousNumber > 0) {
			targetHash = "#slide-" + utils.zeroPadNumber(previousNumber);
			$(window.location).attr('hash', targetHash);
		}
	},

	current: {
		number: function() {
			var number = parseInt(window.location.hash.match(/\d+/), 10);
			if (isNaN(number)) {
				number = 0;
			}
			return number;
		},

		startAt: function() {
			return slides.current.finishAt() - slides.durationPerSlide;
		},

		finishAt: function() {
			return slides.current.number() * slides.durationPerSlide;
		},

		hasSuccessor: function() {
			return slides.current.number() < slides.count();
		},

		navItem: function() {
			var currentNumber = utils.zeroPadNumber(slides.current.number());
			return $("#link-to-slide-" + currentNumber );
		},
		progress: function(currentTime) {
			var startTime, finishTime;
			startTime = slides.current.startAt();
			finishTime = slides.current.finishAt();
			return 100 * ((currentTime-startTime) / (finishTime-startTime));
		}
	},
	next: {
		number: function() {
			return slides.current.number() + 1;
		}
	},
	previous: {
		number: function() {
			if (slides.current.number() > 0) {
				return slides.current.number() - 1;
			}
		},
		navItems: function() {
			var currentNavIndex = slides.current.number() - 1;
			return $("#nav li a:lt("+currentNavIndex+")");
		}
	}
};

utils = {
	zeroPadNumber: function(number) {
		var padded, first, last;
		padded = "00" + number;
		first  = padded.length - 2;
		last   = padded.length;
		return padded.substring(first,last);
	}
};

