//globals
var displayStyle = "list"; // can be 'list' or 'presentation', will be stored in cookie
var slides = 0; // total number of slides
var gUseVerticalArrowKeys = false; // true will cause up / down arrow key events to trigger a slide change, false will trigger default behaviour (i.e. scrolling)

/**
* Applies chosen preferences from the user preferences form and stores them in a cookie if requested. 
* Toggles user input handlers based on preference.
**/
function applyPrefs(event) {
	//global displayStyle

	e = TPG.getEvent(event);
	var f = e ? e.myTarget : $('userPreferences');
	var i;
	displayStyle = f.displayStyle[0].checked ?"presentation":  "list";
	if (displayStyle == "presentation") {
		document.onkeydown = handleKey;
		document.onmousedown = handleMouseDown;
	}	
	else {	
		document.onkeydown = null;
		document.onmousedown = null;
	}
	if (f.savePrefs.checked) {
		var cookie = new TPG.Cookie("slideprefs");
		cookie.displayStyle = displayStyle;
		cookie.store(30);
	}
	parseSlides(displayStyle == "presentation" ? false : true);
	return false;	
}

/***** event handling *****/

function setEventHandlers(displayStyle) {
	var i;
	if (displayStyle == 'presentation') {
		document.onkeydown = handleKey;
		document.onmousedown = handleMouseDown;
	}
	TPG.addEventToNodes(document,'navLink','A','click',handleNavLink)
	TPG.addEventToNodes($('globalSlideNav'),'globalSlideNav','FORM','submit',handleSlideSelect);
	$('userPreferences').onsubmit = applyPrefs;
}

function handleKey(event) {
	//global: slides
	e = TPG.getEvent(event);
	var c = e.myKeyCode;
	var targetIndex;	
	if (!e.ctrlKey && (e.altKey ||TPG.inArray(['SELECT', 'INPUT', 'TEXTAREA'], e.myTarget.nodeName)))// don't change slides while interacting with a widget
		return;
	if (c == TPG.K_ARROWRIGHT || c == TPG.K_PAGEDOWN || (gUseVerticalArrowKeys && TPG.K_ARROWDOWN)) 
		return nextSlide();
	else if (c == TPG.K_ARROWLEFT || c == TPG.K_PAGEUP || (gUseVerticalArrowKeys && TPG.K_ARROWUP))
		return prevSlide();
	else if (c == TPG.K_HOME)
		return changeSlide(0);
	else if (c == TPG.K_END)
		return changeSlide(slides.length -1);
}

function handleMouseDown(event) {
	e = TPG.getEvent(event);
	if (!TPG.inArray(['HTML', 'FIELDSET', 'LABEL', 'SELECT', 'OPTION', 'INPUT', 'TEXTAREA', 'A', 'OBJECT', 'EMBED', 'IFRAME'], e.myTarget.nodeName))//HTML check needed for scrollbars
		nextSlide();
}

function handleNavLink(event) {
	return changeSlide(TPG.getEvent(event).myTarget.hash.substr(6));
}

function handleSlideSelect(event) {
	return changeSlide(TPG.getEvent(event).myTarget.slideSelect.value);
}

/***** SLIDE NAVIGATION *****/

// changes the values of the slide selector dropdowns during slide navigation.
function updateSlideSelectors(index) {
	var slideSelector = $('slideSelectBox');
	var chapterSelector = $('chapterSelectBox');
	//loop backwards over chapter slide indices. The first chapter index which is lower or equal to the current slide index becomes the new value.
	for (var i = chapterSelector.options.length -1; i >= 0 ; i--) {
		if (parseInt(chapterSelector.options[i].value) <= index) {
			chapterSelector.selectedIndex = i;
			break;
		}
	}
	slideSelector.value = index; 
}


/**
* Loops over all slides to toggle the 'nodiplay' classname 
* Is called on load asnd when the presentation style changes
* if showAll is set to true everything will be made visible (used for 'list style' display
* For 'presentation style' display either an index can be specified to be made visible, or the index will be extrated from the current url's hash value
**/
function parseSlides(showAll, slideIndex) {
	//global: slides;
	var slideHash;
	if (!showAll) {	
		if (typeof slideIndex == "number") slideHash = "#slide" + slideIndex;
		else slideHash = window.location.hash; // get the url's hash value (this value is updated dynamically during slide navigation
		if (slideHash.search(/slide[0-9]+/) === -1) // check if the hash has the right pattern, reset to first slide if it doesn't 
			slideHash = "#slide0";
		if (!$(slideHash.slice(1))) //can't find the right node, do nothing.
			return;
	}
	
	for (var i = 0; i < slides.length; i++) {
		if (!showAll) {
			if (slides[i].id == slideHash.slice(1)) {//change title to show current slide number
				TPG.removeClassName(slides[i], "noDisplay"); // ensure current slide is visible
				TPG.changeTitleSuffix('slide ' + (i + 1), 0);
			}
			else TPG.addClassName(slides[i], "noDisplay"); // hide all other slides
		}
		else {//ensure all slides are visible
			TPG.removeClassName(slides[i], "noDisplay"); 
			TPG.removeTitleSuffix();
		}
	}
}

function getCurrentSlideIndex() {
	return window.location.hash.search(/slide[0-9]+/) != -1 ? parseInt(window.location.hash.slice(6)) : 0;	
}

function nextSlide() {
	return changeSlide(getCurrentSlideIndex() + 1);
}
function prevSlide() {
	return changeSlide(getCurrentSlideIndex() - 1);
}

//sets the hash part of the current location to a new index, make slide visiable while hiding the old one
function changeSlide(newSlideIndex) {
	var oldSlideIndex = getCurrentSlideIndex();
	if (newSlideIndex < 0 || newSlideIndex >= slides.length || newSlideIndex == oldSlideIndex) return false;
	
	location.replace("#slide" + newSlideIndex);
	if (displayStyle == "presentation") {
		try {
			TPG.removeClassName($('slide'+ newSlideIndex), 'noDisplay');
			TPG.addClassName($('slide'+ oldSlideIndex), 'noDisplay');
		} catch(e){}
		updateSlideSelectors(newSlideIndex);
		TPG.changeTitleSuffix('slide ' + (newSlideIndex + 1), 1);
	}
	return false;
}


/***** INITIATION *****/

function init() {
	//global: slides
	slides = TPG.getElementsByClassName(document, 'slide', 'div');
	var cookie = new TPG.Cookie("slideprefs");
	if (cookie.displayStyle) {
		 if (cookie.displayStyle == "presentation") {
			displayStyle = "presentation";
		}
	}
	else if ($('styleOptionPres').checked)
		displayStyle = "presentation";
	setEventHandlers(displayStyle);
	if (displayStyle == "presentation") {
		parseSlides();
		$('styleOptionPres').checked = true;
		updateSlideSelectors(getCurrentSlideIndex()); //set values for select elements (slide & chapter selection) 
	}
}

window.onload = init;

