// global variables
var slideshow_image;
var fade_time = 250;
var fade_speed = 25;
var index = 0;
var t;
var status = 'Pause';
var fade = false; 
var slideshow_images = null;
var loaded_image;
var first_keyup = true; // this prevents safari from firing some keyup events twice from a single trigger (!)
var loading = false;
var holding  = false;
var fade_out = false;

// setup event handlers
window.document.onkeyup = keyboard_events;
window.onload = toggle_status;

// Keyboard event handlers
function keyboard_events(e) {
	var e = get_event(e);
	var key_code = get_key_code(e);
	
	if(first_keyup) {
		switch(key_code) {
			case 32: // space bar
			toggle_status();
			break;
			
			case 37: // left
			show_prev_image();
			break;
			
			case 39: // right (put this in a function)
			show_next_image();
			break;
			
			case 38: // up
			increase_delay();
			break;
			
			case 40: // down
			decrease_delay();
			break;
		}
		first_keyup = false;
		setTimeout("first_keyup = true", 5);
	}
}

/******************************
Main logic processes
*******************************/

// toggle between playing and paused
function toggle_status() {
	if(document.getElementById('slideshow_image')) {
		slideshow_image = document.getElementById('slideshow_image');
		slideshow_image.style.display = 'inline';
		resize();
		if(slideshow_images != null) {
			if(status == 'Play') {
				clearTimeout(t);
				set_slideshow_status('Pause');
				message_overlay('Paused', get_display_time());
			} else {
				if(index + 1 == slideshow_images.length) {
					index = -1;
					message_overlay('Replaying', get_display_time() / 2);
				} else {
					message_overlay('Playing', get_display_time() / 2);
				}
				set_slideshow_status('Play');
				hold_image();
			}
		}
	}
}

// display image
function hold_image() {
	load_image(index + 1);
	holding = true;
	t = setTimeout("try_fade_out()", get_display_time());
}

// do not fade out until image is loaded
function try_fade_out() {
	holding = false;
	if(loaded_image.complete) {
		fade_out_image();
	} else {
		loaded_image.onload = fade_out_image;
	}
}

// fade image out
function fade_out_image(value) {
	if(status == 'Play') {
		if(value == null) {
			fade = true;
			fade_out = true;
			value = 1;
		}
		value = Math.round(value * 100) / 100;
		var increment = Math.round((1 / (fade_time / fade_speed)) * 100) / 100;
		if(value >= 0) {
			slideshow_image.style.opacity = value;
			slideshow_image.style.filter = 'alpha(opacity=' + (value * 100) + ')';
			value -= increment;
			setTimeout("fade_out_image(" + value + ")", fade_speed);
		} else {
			fade = false;
			fade_out = false;
			slideshow_image.style.opacity = 0;
			set_next_image();
		}
	} else {
		slideshow_image.style.opacity = 1;
		slideshow_image.style.filter = 100;
	}
}

// auto-increment the slideshow forward
function set_next_image() {
	clearTimeout(t);
	index++;
	swap_loaded_image();
	update_info();
	if(status == 'Play') {
		fade_in_image();
	}
}

// fade image in
function fade_in_image(value) {
	if(value == null) {
		fade = true;
		value = 0;
	}
	value = Math.round(value * 100) / 100;
	var increment = Math.round((1 / (fade_time / fade_speed)) * 100) / 100;
	if(value <= 1) {
		slideshow_image.style.opacity = value;
		slideshow_image.style.filter = 'alpha(opacity=' + (value * 100) + ')';
		value += increment;
		setTimeout("fade_in_image(" + value + ")", fade_speed);
	} else {
		fade = false;
		slideshow_image.style.opacity = 1;
		hold_image();
	}
}


/******************************
Helper Functions
*******************************/

// manually increment the slideshow backward
function show_prev_image() {
	if(!fade) {
		if(index > 0) {
			if(!loading) {
				hide_overlay();
				first_keyup = true;
				index--;
				clearTimeout(t);
				load_image(index);
				set_slideshow_status('Pause');
				if(loaded_image.complete) {
					swap_loaded_image();
					update_info();
				} else {
					message_overlay('loading...');
					loading = true;
					loaded_image.onload = function() {
						loading = false;
						hide_overlay();
						swap_loaded_image();
						update_info();
					}
				}
			}
		} else {
			message_overlay('Beginning', get_display_time() / 2)
		}
	} else {
		setTimeout("show_prev_image()", fade_time);
	}
}

// manually increment the slideshow forward
function show_next_image() {
	if(index + 1 < slideshow_images.length) {
		if(!loading) {
			load_image(index + 1);
			set_slideshow_status('Pause');
			if(loaded_image.complete) {
				set_next_image();
			} else {
				message_overlay('loading...');
				loading = true;
				loaded_image.onload = function() {
					loading = false;
					hide_overlay();
					set_next_image();
				}
			}
		}
	} else {
		message_overlay('End', get_display_time() / 2);
	}
}

// show a transparent textbox on top of the image
function message_overlay(text, duration) {
	var slideshow_overlay = document.getElementById('slideshow_overlay');
	if(slideshow_overlay) {
		slideshow_overlay.removeChild(slideshow_overlay.firstChild);
		slideshow_overlay.style.top = slideshow_image.offsetTop;
		slideshow_overlay.style.left = slideshow_image.offsetLeft;
		slideshow_overlay.style.width = slideshow_image.offsetWidth;
		slideshow_overlay.style.opacity = .5;
		slideshow_overlay.style.filter = 'alpha(opacity=50)';
		slideshow_overlay.appendChild(document.createTextNode(text));
		slideshow_overlay.style.display = 'block';
		if(duration) {
			setTimeout("hide_overlay()", duration);
		}
	}
}

// fade the transparent textbox out
function hide_overlay(value) {
	var slideshow_overlay = document.getElementById('slideshow_overlay');
	if(value == null) {
		value = slideshow_overlay.style.opacity;
	}
	value = Math.round(value * 100) / 100;
	var increment = Math.round((1 / (fade_time / fade_speed)) * 100) / 100;
	if(value >= 0) {
		slideshow_overlay.style.opacity = value;
		slideshow_overlay.style.filter = 'alpha(opacity=' + (value * 100) + ')';
		value -= increment;
		setTimeout("hide_overlay(" + value + ")", fade_speed + 50);
	} else {
		slideshow_overlay.style.opacity = 0;
	}
}

// preload an image, and optionally perform a call-back function
function load_image(image, call_back) {
	if(image < slideshow_images.length) {
		loaded_image = new Image();
		if(loaded_image.setAttribute) {
			loaded_image.setAttribute('src', get_image_src(image));
		} else {
			loaded_image.src = get_image_src(image);
		}
		if(loaded_image.complete) {
			if(call_back) {
				call_back();
			}
		} else {
			loaded_image.onload = function() {
				if(call_back) {
					call_back();
				}
			}
		}
	} else {
		setTimeout("message_overlay('Finished'," + get_display_time() + ");set_slideshow_status('end')", get_display_time() / 2);
	}
}

// set image source to that of the pre-loaded image
function swap_loaded_image() {
	slideshow_image.style.display = 'none';
	slideshow_image.width = loaded_image.width;
	slideshow_image.height = loaded_image.height;
	slideshow_image.src = loaded_image.src;
	resize();
	slideshow_image.style.display = 'inline';
}

// indicate which HTML object represents the delay time
function set_display_time(obj) {
	var container = obj.parentNode;
	for(i = 0; i < container.childNodes.length; i++) {
		if(container.childNodes[i].nodeType == 1) {
			container.childNodes[i].className = '';
		}
	}
	obj.className = 'slideshow_delay';
}

// return the HTML object that represents the delay time
function get_display_time() {
	var container = document.getElementById('slideshow_controls');
	for(i = 0; i < container.childNodes.length; i++) {
		if(container.childNodes[i].nodeType == 1) {
			if(container.childNodes[i].className == 'slideshow_delay') {
				return container.childNodes[i].id;
			}
		}
	}
}

// set image height/width relative to current viewport
function resize() {
	slideshow_image = document.getElementById('slideshow_image');
	temp_image = new Image();
	temp_image.src = slideshow_image.src;
	if(temp_image.height > get_viewport('height') - 40) {
		var new_height = get_viewport('height') - 40;
		slideshow_image.width = (temp_image.width * new_height) / temp_image.height;
		slideshow_image.height = new_height;
	}
	if(slideshow_image.width > get_viewport('width') - 30) {
		var new_width = get_viewport('width') - 30;
		slideshow_image.height = (slideshow_image.height * new_width) / slideshow_image.width;
		slideshow_image.width = new_width;
	}
}


// update title, url, and viewable index
function update_info() {
	set_slideshow_title(get_image_title());
	set_slideshow_index(index + 1);
}

// set slideshow title in DOM
function set_slideshow_title(title) {
	var slideshow_title = document.getElementById('slideshow_title');
	if(slideshow_title.firstChild) {
		slideshow_title.firstChild.nodeValue = title;
	}
}

// set viewable index in DOM
function set_slideshow_index(_index) {
	var slideshow_index = document.getElementById('slideshow_index')
	slideshow_index.removeChild(slideshow_index.firstChild);
	slideshow_index.appendChild(document.createTextNode(_index));
}

// set global variable and viewable indicator
function set_slideshow_status(_status) {
	if(_status == 'Play') {
		status = _status;
		var other_status = 'Pause';
	} else if(_status == 'Pause') {
		status = _status;
		var other_status = 'Play';
	} else if(_status == 'end') {
		status = 'Pause';
		var other_status = 'Replay';
	}
	var slideshow_status = document.getElementById('slideshow_status');
	slideshow_status.removeChild(slideshow_status.firstChild);
	slideshow_status.appendChild(document.createTextNode(other_status));
}

// jump to a higher image delay setting
function increase_delay() {
	if(!fade) {
		var current_delay_obj = document.getElementById(get_display_time());
		var container = current_delay_obj.parentNode;
		var get_next = false;
		for(i = 0; i < container.childNodes.length; i++) {
			if(container.childNodes[i].nodeType == 1) {
				container.childNodes[i].className = '';
				if(get_next) {
					if(parseInt(container.childNodes[i].id) == container.childNodes[i].id) {
						delay_obj = container.childNodes[i];
						get_next = false;
					}
				} else if(container.childNodes[i].id == current_delay_obj.id) {
					get_next = true;
				}
				
				if(parseInt(container.childNodes[i].id) == container.childNodes[i].id) {
					last_obj = container.childNodes[i];
				}
			}
		}
		if(get_next) {
			set_display_time(last_obj);
		} else {
			set_display_time(delay_obj);
		}
		clearTimeout(t);
		t = setTimeout("fade_out_image()", get_display_time());
	} else {
		setTimeout('increase_delay()', fade_time);
	}
}

// jump to a lower image delay setting
function decrease_delay() {
	if(!fade) {
		var current_delay_obj = document.getElementById(get_display_time());
		var container = current_delay_obj.parentNode;
		var get_next = false;
		for(i = container.childNodes.length - 1; i >= 0; i--) {
			if(container.childNodes[i].nodeType == 1) {
				container.childNodes[i].className = '';
				if(get_next) {
					if(parseInt(container.childNodes[i].id) == container.childNodes[i].id) {
						delay_obj = container.childNodes[i];
						get_next = false;
					}
				} else if(container.childNodes[i].id == current_delay_obj.id) {
					get_next = true;
				}
				
				if(parseInt(container.childNodes[i].id) == container.childNodes[i].id) {
					first_obj = container.childNodes[i];
				}
			}
		}
		if(get_next) {
			set_display_time(first_obj);
		} else {
			set_display_time(delay_obj);
		}
		clearTimeout(t);
		t = setTimeout("fade_out_image()", get_display_time());
	} else {
		setTimeout('decrease_delay()', fade_time);
	}
}

// get url element of images array
function get_image_src(_index) {
	if(_index == null) {
		_index = index;
	}
	return slideshow_images[_index][0];
}

// get title element of images array
function get_image_title(_index) {
	if(_index == null) {
		_index = index;
	}
	if(slideshow_images[_index][1] == '') {
		return 'image ' + (_index + 1);
	} else {
		return slideshow_images[_index][1];
	}
}

/******************************
The following are from quirksmode.com
*******************************/

// cross-browser function to get the dimensions of the viewable window (viewport)
function get_viewport(dimension) {
	var x,y;
	if (self.innerHeight) { // all except Explorer
		x = self.innerWidth;
		y = self.innerHeight;
	}
	else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
		x = document.documentElement.clientWidth;
		y = document.documentElement.clientHeight;
	}
	else if (document.body) { // other Explorers
		x = document.body.clientWidth;
		y = document.body.clientHeight;
	}
	
	if(dimension == 'height') {
		return y;
	} else if(dimension == 'width') {
		return x;
	}
}

// cross-browser function to get the appropriate event object
function get_event(e) {
	if(!e) {
		return window.event;
	} else {
		return e;
	}
}

// cross-browser function to determine which key was pressed
function get_key_code(e) {
	if(e.keyCode) {
		return e.keyCode;
	} else if (e.which) {
		return e.which;
	}
}
