/*
 * Gallery - a web based photo album viewer and editor
 * Copyright (C) 2000-2007 Bharat Mediratta
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
 */

var DEBUG_MESSAGES = 8;
var msgnumber = 1;

/* Cross-browser event handling, by Scott Andrew */
function addEvent(element, eventType, lamdaFunction, useCapture) {
    if (element.addEventListener) {
	element.addEventListener(eventType, lamdaFunction, useCapture);
	return true;
    } else if (element.attachEvent) {
	var r = element.attachEvent('on' + eventType, lamdaFunction);
	return r;
    } else {
	return false;
    }
}

/* Kills an event's propagation and default action */
function knackerEvent(eventObject) {
    if (eventObject && eventObject.stopPropagation) {
	eventObject.stopPropagation();
    }
    if (window.event && window.event.cancelBubble) {
	window.event.cancelBubble = true;
    }

    if (eventObject && eventObject.preventDefault) {
	eventObject.preventDefault();
    }
    if (window.event) {
	window.event.returnValue = false;
    }
}

/*
 * Safari doesn't support canceling events in the standard way, so we must
 * hard-code an event return false for it to work.
 */
function cancelEventSafari() {
    return false;
}

/*
 * Cross-browser style extraction, from the JavaScript & DHTML Cookbook
 * <http://www.oreillynet.com/pub/a/javascript/excerpt/JSDHTMLCkbk_chap5/index5.html>
 */
function getElementStyle(elementID, CssStyleProperty) {
    var element = document.getElementById(elementID);
    if (element.currentStyle) {
	return element.currentStyle[toCamelCase(CssStyleProperty)];
    } else if (window.getComputedStyle) {
	var compStyle = window.getComputedStyle(element, '');
	return compStyle.getPropertyValue(CssStyleProperty);
    } else {
	return '';
    }
}

function createCookie(name, value, days) {
    var expires = '';
    if (days) {
	var date = new Date();
	date.setTime(date.getTime() + (days*24*60*60*1000));
	var expires = '; expires=' + date.toGMTString();
    }
    document.cookie = name + '=' + value + expires + '; path=/';
}

function readCookie(name) {
    var cookieCrumbs = document.cookie.split(';');
    var nameToFind = name + '=';
    for (var i = 0; i < cookieCrumbs.length; i++) {
	var crumb = cookieCrumbs[i];
	while (crumb.charAt(0) == ' ') {
	    crumb = crumb.substring(1, crumb.length); /* delete spaces */
	}
	if (crumb.indexOf(nameToFind) == 0) {
	    return crumb.substring(nameToFind.length, crumb.length);
	}
    }
    return null;
}

function eraseCookie(name) {
    createCookie(name, '', -1);
}

/*
 * CamelCases CSS property names.
 * From <http://dhtmlkitchen.com/learn/js/setstyle/index4.jsp>
 */
function toCamelCase(CssProperty) {
    var stringArray = CssProperty.toLowerCase().split('-');
    if (stringArray.length == 1) {
	return stringArray[0];
    }
    var ret = (CssProperty.indexOf("-") == 0)
	      ? stringArray[0].charAt(0).toUpperCase() + stringArray[0].substring(1)
	      : stringArray[0];
    for (var i = 1; i < stringArray.length; i++) {
	var s = stringArray[i];
	ret += s.charAt(0).toUpperCase() + s.substring(1);
    }
    return ret;
}

/* Adds a status message to the page; very useful for debugging without alerts */
function addMessage(msg) {
    if (DEBUG_AJAXIAN) {
	var msgarea = document.getElementById('msgarea');
	if (msgarea) {
	    msgarea.style.display = 'block';
	    if (msgarea.getElementsByTagName('h4').length < 1) {
		var debugHeading = document.createElement('h4');
		debugHeading.appendChild(document.createTextNode('Debug output'));
		msgarea.appendChild(debugHeading);
	    }
	    if (msgarea.getElementsByTagName('p').length > DEBUG_MESSAGES) {
		msgarea.removeChild(msgarea.getElementsByTagName('p')[0]);
	    }
	    var note = document.createElement('p');
	    note.appendChild(document.createTextNode(msgnumber + ': ' + msg));
	    msgnumber++;
	    msgarea.appendChild(note);
	}
    }
}
/*
 * Gallery - a web based photo album viewer and editor
 * Copyright (C) 2000-2007 Bharat Mediratta
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
 */

/* Global Variables */

var thumbnails;			/* array of thumbnails */
var currentImageIndex;		/* index into thumbnails array */
var mainPhoto;			/* The central image */
var photoScalingInterval;	/* scaling animation tracker */
var showLoadingTimeout;		/* Cancel the loading message display */
var showImageDataFadeTimeout	/* Fade in image data block */

var MAIN_PHOTO_WIDTH = 460;	/* Width each image is resized to when first loaded */
var PHOTO_MINIMISED = 300;	/* Width each image is resized down to when clicked */
var SCALE_DOWN_FACTOR = 12;	/* Pixels that an image scales down by at each step */
var SCALE_UP_FACTOR = 18;	/* Pixels that an image scales *up* by at each step */

/* @REVISIT: For preloading... */
fullsizePhotos = new Array();
fullsizeCount = 0;

/* Initialisation */
addEvent(window, 'load', init, false);

function init() {
    if (!document.getElementById) {
	/* Required functionality for even the most basic DHTML. */
	return;
    }
    /* Set up thumbnails */
    var thumbholder = document.getElementById('gsThumbMatrix');
    if (!thumbholder) {
	setupBackToAlbumLink(); /* Not an album page */
	return;
    }
    thumbnails = thumbholder.getElementsByTagName('img');
    for (var i = 0; i < thumbnails.length; i++) {
	thumbnails[i].thumbIndex = i;
	addEvent(thumbnails[i], 'click', activateThumbnail, false);
	thumbnails[i].onclick = cancelEventSafari;
    }

    /*
     * If the user has just come from a photo page, they may have a cookie set that holds the index
     * of the image that was active in the show when they left. Now they can rejoin at that point.
     */
    if (readCookie('slideshowOffset') != null &&
	    Number(readCookie('slideshowOffset')) < thumbnails.length) {
	currentImageIndex = Number(readCookie('slideshowOffset'));
	eraseCookie('slideshowOffset');
	addMessage('Restarting slideshow at index ' + currentImageIndex);
    } else {
	currentImageIndex = 0;
    }

    if (slideshowImages.length > 0) {
      setupMainImage();
      switchImages(currentImageIndex, true);
    }

    setupSubAlbums();
    showPhotoDetails();
}

/* Called each time a new image is switched to */
function setupMainImage() {
    mainPhoto = document.getElementById('main-image');

    if (slideshowImageWidths[currentImageIndex] < 0
	    || MAIN_PHOTO_WIDTH <= slideshowImageWidths[currentImageIndex]) {
	mainPhoto.style.width = MAIN_PHOTO_WIDTH + 'px';
    } else {
	/*
	 * The image is below our ideal slideshow width, so we don't want to stretch it
	 * horizontally.  Instead we center the image that we have a little better.
	 */
	mainPhoto.style.width = slideshowImageWidths[currentImageIndex] + 'px';
	mainPhoto.style.left = parseInt(getElementStyle(mainPhoto.id, 'left')) +
	    ((MAIN_PHOTO_WIDTH - slideshowImageWidths[currentImageIndex])/2) + 'px';
    }
    mainPhoto.style.height = 'auto'; /* @REVISIT - Safari doesn't play nice with this */

    mainPhoto.origWidth = parseInt(getElementStyle(mainPhoto.id, 'width'));
    mainPhoto.origLeft = parseInt(getElementStyle(mainPhoto.id, 'left'));
    mainPhoto.galleryimg = 'no'; /* Disables IE's image toolbar, which was causing flicker */

    addEvent(mainPhoto, 'click', showPhotoDetails, false);
}

function activateThumbnail(e) {
    /* Find the source element through varying levels of browser support */
    var targetElement = window.event ? window.event.srcElement : e ? e.target : null;
    if (!targetElement) {
	return;
    }
    knackerEvent(e);
    switchImages(targetElement.thumbIndex);
    targetElement.blur();	/* Remove focus halo */
    showPhotoDetails();
}

function switchImages(thumbIndex, firstLoad) {
    removeImageDataBlock();
    if (currentImageIndex == thumbIndex && !firstLoad) {
	addMessage("That image is already selected.");
	return;
    }
    /* Wrap around */
    if (thumbIndex < 0) {
	thumbIndex = thumbnails.length - 1;
    } else if (thumbIndex == thumbnails.length) {
	thumbIndex = 0;
    }
    if (slideshowImageWidths[thumbIndex] < 0) {
	/* This item is not a photo.. redirect to view it */
	if (!firstLoad) {
	    location = slideshowImages[thumbIndex];
	} else {
	    hideLoadingMessage();
	}
	return;
    }
    highlightCurrentThumb(thumbIndex);
    updateItemTitle(thumbIndex);

    hideLoadingMessage();

    var newImageSrc = slideshowImages[thumbIndex];
    var newImage = document.createElement('img');

    mainPhoto.id = null; /* Isn't enough in some browsers */
    mainPhoto.removeAttribute('id');

    newImage.id = 'main-image';
    addEvent(newImage, 'load', bigPhotoLoad, false);
    addEvent(newImage, 'error', bigPhotoFail, false);

    if (slideshowState == PLAYING) {
	pause();
	returnToPlaying = true;
    }

    /* Avoid showing loading message if its going to be fast */
    showLoadingTimeout = setTimeout("showLoadingMessage()", 600);

    addMessage("Swapping " + currentImageIndex + ", and " + thumbIndex + "...");
    currentImageIndex = thumbIndex;

    newImage.src = newImageSrc;
    mainPhoto.parentNode.removeChild(mainPhoto);
    document.getElementById('sliding-frame').getElementsByTagName('p')[0].appendChild(newImage);
    setupMainImage();

    if (mainPhoto.state == 'downsized') {
	insertimagedatablock();
    }
}

function bigPhotoLoad() {
    mainPhoto.style.height = 'auto';
    addMessage('Photo loaded');
    hideLoadingMessage();

    /*
     * The little switcheroo below prevents a problem with IE incorrectly calculating the 'height'
     * property for an image that has had its width changed when set to 'auto' (they should scale
     * together). Should be imperceptible in other browsers.
     */
    mainPhoto.style.height = '345px';
    mainPhoto.style.height = 'auto';
    if (returnToPlaying) {
	play();
    }
}

function bigPhotoFail() {
    addMessage('FAIL: Photo failed to load...');
    addMessage(mainPhoto.src);
    hideLoadingMessage();
    if (slideshowState == PLAYING) {
	advanceSlideShow();
    }
}

function showLoadingMessage() {
    var loadingMsg = document.createElement('div');
    loadingMsg.id = 'loading';
    loadingMsg.appendChild(document.createTextNode(LOADING_IMAGE));
    document.getElementById('main-image-container').appendChild(loadingMsg);
}

function hideLoadingMessage() {
    clearTimeout(showLoadingTimeout);
    var loading = document.getElementById('loading');
    if (loading && getElementStyle(loading.id, '-moz-opacity') > 0.0) {
	loading.style.MozOpacity = parseFloat(getElementStyle(loading.id, '-moz-opacity')) - 0.05;
	showLoadingTimeout = setTimeout("hideLoadingMessage()", 50);
    } else if (loading) {
	loading.parentNode.removeChild(loading);
    }
}

function highlightCurrentThumb(thumbIndex) {
    /* First, un-highlight the current image... */
    thumbnails[currentImageIndex].className =
	thumbnails[currentImageIndex].className.replace(/\bcurrentImage\b/, '');
    thumbnails[thumbIndex].className += ' currentImage';
}

function updateItemTitle(thumbIndex) {
    var itemTitle = document.getElementById('item-title').firstChild;
    itemTitle.data = thumbnails[thumbIndex].getAttribute('alt');
}

/*
 * Photo -scaling functions
 */
function showPhotoDetails(e) {
	if(mainPhoto)
	{
		addMessage('scaling image, dimensions: ' + mainPhoto.origWidth + 'x' + mainPhoto.origHeight);
		clearInterval(photoScalingInterval);
		if (slideshowState == PLAYING) {
		pause();
		returnToPlaying = true;
		}
	
		//if (mainPhoto.state != 'downsized') {
		photoScalingInterval = setInterval("downSizePhoto()", 30);
		mainPhoto.state = 'downsized';
	   /* } else {
		removeImageDataBlock();
		photoScalingInterval = setInterval("upSizePhoto()", 20);
		mainPhoto.state = 'upsized';
		}*/
	}
}

function downSizePhoto() {
    if (parseInt(mainPhoto.style.width) > PHOTO_MINIMISED ||
	    parseInt(getElementStyle(mainPhoto.id, 'left')) > 40) {
	if (parseInt(mainPhoto.style.width) > PHOTO_MINIMISED) {
	    mainPhoto.style.width = parseInt(mainPhoto.style.width) - SCALE_DOWN_FACTOR + 'px';
	}

	/* REVISIT Works in everything but Safari... */
	mainPhoto.style.height = 'auto';

	if (parseInt(getElementStyle(mainPhoto.id, 'left')) > 40) {
	    mainPhoto.style.left = (parseInt(getElementStyle(mainPhoto.id, 'left')) -
		mainPhoto.origLeft/12) + 'px';
	}
	if (getElementStyle(mainPhoto.id, 'top') == 'auto') {
	    mainPhoto.style.top = '0';
	}
	if (parseInt(getElementStyle(mainPhoto.id, 'top')) < 40) {
	    mainPhoto.style.top = (parseInt(getElementStyle(mainPhoto.id, 'top')) + 5) + 'px';
	}
    } else {
	clearInterval(photoScalingInterval);
	addMessage('Image scaled to ' + mainPhoto.style.width + 'x' + mainPhoto.style.height);
	mainPhoto.state = 'downsized';
	insertimagedatablock();
    }
}

function upSizePhoto() {
    if (parseInt(mainPhoto.style.width) < mainPhoto.origWidth ||
	    parseInt(getElementStyle(mainPhoto.id, 'left')) < mainPhoto.origLeft) {
	if (parseInt(mainPhoto.style.width) < mainPhoto.origWidth-5) {
	    mainPhoto.style.width = (parseInt(mainPhoto.style.width) + SCALE_UP_FACTOR) + 'px';
	}
	if (parseInt(getElementStyle(mainPhoto.id, 'left')) < mainPhoto.origLeft) {
	    mainPhoto.style.left = (parseInt(getElementStyle(mainPhoto.id, 'left')) +
		mainPhoto.origLeft/10) + 'px';
	}
	if (parseInt(getElementStyle(mainPhoto.id, 'top')) > 0) {
	    mainPhoto.style.top = (parseInt(getElementStyle(mainPhoto.id, 'top')) - 5) + 'px';
	}
    } else {
	/* Clean up and reset */
	clearInterval(photoScalingInterval);
	mainPhoto.style.width = mainPhoto.origWidth + 'px';
	mainPhoto.style.height = 'auto';
	mainPhoto.style.left = mainPhoto.origLeft + 'px';
	mainPhoto.style.top = 'auto';
	addMessage('Image scaled back to ' + mainPhoto.width + 'x' + mainPhoto.height);
	mainPhoto.state = 'upsized';
	if (returnToPlaying) {
	    play();
	}
    }
}

function insertimagedatablock() {
    var dataBlock = document.createElement('div');
    dataBlock.id = 'imagedatablock';

    var dataBlockHeading = document.createElement('h3');
    dataBlockHeading.appendChild(document.createTextNode(PHOTO_DATA));
    dataBlock.appendChild(dataBlockHeading);

    if (thumbnails[currentImageIndex].className.match(/size:=([0-9]+)=/)) {
	var imageSize = Number(RegExp.$1) / 1024;
	var sizeInfo = document.createElement('p');
	sizeInfo.appendChild(
	    document.createTextNode(FILE_SIZE.replace(/%SIZE%/, Math.round(imageSize))));
	dataBlock.appendChild(sizeInfo);
    }
    if (thumbnails[currentImageIndex].className.match(/summary:=([^=]+)=/)) {
	var summaryInfo = document.createElement('p');
	summaryInfo.appendChild(document.createTextNode(SUMMARY + RegExp.$1));
	dataBlock.appendChild(summaryInfo);
    }
    if (thumbnails[currentImageIndex].className.match(/description:=(.+)=/)) {
	var descriptionInfo = document.createElement('p');
       
        var idescript=RegExp.$1;

        idescript=idescript.replace('[/url]','</a>'); 
        idescript=idescript.replace('[url=','<a href="');
        idescript=idescript.replace(']','">');

	/*descriptionInfo.appendChild(document.createTextNode(DESCRIPTION + idescript));*/
        descriptionInfo.innerHTML=DESCRIPTION + idescript;
	dataBlock.appendChild(descriptionInfo);
    }

    var fullsizeLink = document.createElement('a');
    fullsizeLink.id = 'fullsizelink';
    fullsizeLink.href = thumbnails[currentImageIndex].parentNode.href;
	/*+ (thumbnails[currentImageIndex].parentNode.href.indexOf('?') >= 0 ? '&' : '?')
	+ 'thumbIndex=' + currentImageIndex;*/
    /* Allow a user to rejoin the slideshow at this point */
    addEvent(fullsizeLink, 'click', saveCurrentImageIndex, false);

    fullsizeLink.appendChild(document.createTextNode(VIEW_IMAGE));
    var linkPara = document.createElement('p');
    linkPara.appendChild(fullsizeLink);
    dataBlock.appendChild(linkPara);

    /* In Gecko-based browsers, this'll fade the data block in smoothly. */
    /*dataBlock.style.MozOpacity = 0.2;*/
    showImageDataFadeTimeout = setTimeout('fadeInImageDataBlock()', 50);

    document.getElementById('main-image-container').appendChild(dataBlock);
}

function fadeInImageDataBlock() {
    clearTimeout(showImageDataFadeTimeout);
    var dataBlock = document.getElementById('imagedatablock');
    /* Don't bring -moz-opacity all the way to 1.0, as it causes flicker in Firefox 1.0 */
    if (dataBlock && getElementStyle(dataBlock.id, '-moz-opacity') < 0.92) {
	dataBlock.style.MozOpacity = parseFloat(getElementStyle(dataBlock.id, '-moz-opacity')) + 0.08;
	showImageDataFadeTimeout = setTimeout('fadeInImageDataBlock()', 50);
    }
}

function removeImageDataBlock() {
    var dataBlock = document.getElementById('imagedatablock');
    if (dataBlock) {
	dataBlock.parentNode.removeChild(dataBlock);
    }
}

/* Subalbums table */

function setupSubAlbums() {
    /* First check if there is a sub-album table */
    if (!document.getElementById('gsSubAlbumMatrix')) {
	return;
    }
    var subs = document.getElementById('gsSubAlbumMatrix').getElementsByTagName('td');
    for (var i = 0; i < subs.length; i++) {
	addEvent(subs[i], 'click', selectSubAlbum, false);
	var hasLink = subs[i].getElementsByTagName('a')[0];
	if (hasLink) {
	    addEvent(subs[i], 'mouseover', highlightSubAlbum, true);
	    addEvent(subs[i], 'mouseout', unHighlightSubAlbum, true);
	}
    }
}

function highlightSubAlbum(e) {
    /* Find the source element through varying levels of browser support */
    var targetElement = window.event ? window.event.srcElement : e ? e.target : null;
    if (!targetElement) {
	return;
    }
    while (targetElement.nodeName.toLowerCase() != 'td' &&
	   targetElement.nodeName.toLowerCase() != 'body') {
	targetElement = targetElement.parentNode;
    }
    if (targetElement.nodeName.toLowerCase() == 'body') {
	return;
    }
    targetElement.className += ' sahover';
}

function unHighlightSubAlbum(e) {
    /* Find the source element through varying levels of browser support */
    var targetElement = window.event ? window.event.srcElement : e ? e.target : null;
    if (!targetElement) {
	return;
    }
    while (targetElement.nodeName.toLowerCase() != 'td' &&
	   targetElement.nodeName.toLowerCase() != 'body') {
	targetElement = targetElement.parentNode;
    }
    if (targetElement.nodeName.toLowerCase() == 'body') {
	return;
    }
    targetElement.className = targetElement.className.replace(/\bsahover\b/, '');
}

function selectSubAlbum(e) {
    /* Find the source element through varying levels of browser support */
    var targetElement = window.event ? window.event.srcElement : e ? e.target : null;
    if (!targetElement) {
	return;
    }
    knackerEvent(e);

    while (targetElement.nodeName.toLowerCase() != 'td' &&
	   targetElement.nodeName.toLowerCase() != 'body') {
	targetElement = targetElement.parentNode;
    }
    if (targetElement.nodeName.toLowerCase() == 'body') {
	return;
    }
    eraseCookie('slideshowOffset');
    var firstlink = targetElement.getElementsByTagName('a')[0];
    if (firstlink) {
	window.location = firstlink.href;
    }
}

/* Photo page functions */

function setupBackToAlbumLink() {
    var pageLinks = document.getElementsByTagName('a');
    for (var i = 0; i < pageLinks.length; i++) {
	if (pageLinks[i].className.match(/\bbacktoalbum\b/)) {
	    addEvent(pageLinks[i], 'click', saveCurrentImageIndex, false);
	}
    }
}

function saveCurrentImageIndex() {
    if (window.location.toString().match(/thumbIndex=([0-9]+)/)) {
	createCookie('slideshowOffset', RegExp.$1);
    } else if (currentImageIndex) {
	createCookie('slideshowOffset', currentImageIndex);
    }
}
/*
 * Gallery - a web based photo album viewer and editor
 * Copyright (C) 2000-2007 Bharat Mediratta
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
 */

/* Global Variables */

/* play/pause state of slideshow */
var slideshowState;
var PAUSED = 0;
var PLAYING = 1;
/* After an image load, should the slideshow continue? */
var returnToPlaying;

/* Number of seconds before the images switch */
var SECONDS_BETWEEN_IMAGES = 4;
/* Tracks the time between images in the show */
var slideShowInterval;

/* Easy access to slideshow controls elements */
var controls;
/* Tracks the hiding/showing of the controls */
var showControlsInterval;
var hideControlsInterval;
/* vertical offset in pixels for controls */
var CONTROLS_HIDDEN_DEPTH = -35;

/* Initialisation */
addEvent(window, 'load', slideShow, false);

function slideShow() {
    if (!document.getElementById) {
	return;
    }
    var playpause = document.getElementById('controls-play');
    if (!playpause) {
	return;
    }

    /* Set up controls */
    addEvent(playpause, 'click', togglePlayPause, false);
    addEvent(document.getElementById('controls-left'), 'click', skipLeft, false);
    addEvent(document.getElementById('controls-right'), 'click', skipRight, false);

    /* Add animation to controls and thumbs */
    addEvent(document.getElementById('slideshow-controls'), 'mousemove', showControls, false);
    addEvent(document.getElementById('slideshow-controls'), 'mouseout', hideControlBar, false);

    /* Load in controls and thumbs */
    showControls();

    /* Set initial state */
    pause();
    returnToPlaying = false;
}

function advanceSlideShow() {
    if (slideshowState == PLAYING) {
	switchImages(currentImageIndex + 1);
    }
}

function play() {
    slideshowState = PLAYING;
    resetInterval();
    returnToPlaying = true;
    /* Swap Images */
    var theImage =
	document.getElementById('controls-play').getElementsByTagName('img')[0];
    theImage.src = theImage.src.replace(/play/, 'pause');
}

function pause() {
    slideshowState = PAUSED;
    clearInterval(slideShowInterval);
    returnToPlaying = false;
    /* Swap Images */
    var theImage =
	document.getElementById('controls-play').getElementsByTagName('img')[0];
    theImage.src = theImage.src.replace(/pause/, 'play');
}

function resetInterval() {
    clearInterval(slideShowInterval);	/* Just in case... */
    slideShowInterval =
	setInterval("advanceSlideShow()", SECONDS_BETWEEN_IMAGES * 1000);
}

function skipLeft() {
    switchImages(currentImageIndex - 1);
    resetInterval();
}

function skipRight() {
    switchImages(currentImageIndex + 1);
    resetInterval();
}

function togglePlayPause() {
    if (slideshowState == PAUSED) {
	play();
    } else {
	pause();
    }
}

function showControls() {
    controls = document.getElementById('control-buttons');
    clearInterval(showControlsInterval);
    clearInterval(hideControlsInterval);
    controls.state = 'showing';
    if (controls.state != 'shown') {
	showControlsInterval = setInterval('animateControlShow()', 15);
    }
}

function hideControlBar() {
    clearInterval(hideControlsInterval);
    /*
     * Pass an anonymous function to setTimeout that is only executed after
     * 1500 milliseconds has passed. Mousing over the controls' action area
     * within this time will reset the timeout.
     */
    hideControlsInterval = setTimeout(function() {
	if (controls.state == 'shown' || controls.state == 'showing') {
	  hideControlsInterval = setInterval('animateControlHide()', 50);
	}
    }, 1500);
}

function animateControlShow() {
    var pos = parseInt(getElementStyle(controls.id, 'top'));
    if (pos < 0) {
	controls.style.top = (pos + 3) + 'px';
    } else {
	clearInterval(showControlsInterval);
	controls.state = 'shown';
    }
}

function animateControlHide() {
    var pos = parseInt(getElementStyle(controls.id, 'top'));
    if (pos > CONTROLS_HIDDEN_DEPTH) {
	controls.style.top = (pos - 3) + 'px';
    } else {
	clearInterval(hideControlsInterval);
	controls.state = 'hidden';
    }
}