// Set up variables
var intCurrentImage = 0;
var intNextImage = 1;
var intSpeed = 5000;
var arrImages = new Array();
var arrImageHeights = new Array();
var arrImageSources = new Array();
var arrImgNodes = new Array();
var arrHeaderNodes = new Array();
var arrCaptionNodes = new Array();
var arrDataLoaded = new Array();
var boolAllLoaded = false;
var boolPaused = false;
var boolCurrentlyFading = false;
var objInterval;

// Set up slider variables
var objSliderTemplate = {
	'b_vertical' : false,
	'b_watch': false,
	'n_controlWidth': 149,
	'n_controlHeight': 17,
	'n_sliderWidth': 9,
	'n_sliderHeight': 17,
	'n_pathLeft' : 1,
	'n_pathTop' : 0,
	'n_pathLength' : 138,
	's_imgControl': 'css/images/slider_background.gif',
	's_imgSlider': 'css/images/slider.gif',
	'n_zIndex': 1
}

var objSliderInit = {
	's_name' : 'sliderValue',
	'n_minValue' : 0,
	'n_maxValue' : 10000,
	'n_value' : 5000,
	'n_step' : 1
}

var BrowserDetect = {
	init: function () {
		this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
		this.version = this.searchVersion(navigator.userAgent)
			|| this.searchVersion(navigator.appVersion)
			|| "an unknown version";
		this.OS = this.searchString(this.dataOS) || "an unknown OS";
	},
	searchString: function (data) {
		for (var i=0;i<data.length;i++)	{
			var dataString = data[i].string;
			var dataProp = data[i].prop;
			this.versionSearchString = data[i].versionSearch || data[i].identity;
			if (dataString) {
				if (dataString.indexOf(data[i].subString) != -1)
					return data[i].identity;
			}
			else if (dataProp)
				return data[i].identity;
		}
	},
	searchVersion: function (dataString) {
		var index = dataString.indexOf(this.versionSearchString);
		if (index == -1) return;
		return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
	},
	dataBrowser: [
		{ 	string: navigator.userAgent,
			subString: "OmniWeb",
			versionSearch: "OmniWeb/",
			identity: "OmniWeb"
		},
		{
			string: navigator.vendor,
			subString: "Apple",
			identity: "Safari"
		},
		{
			prop: window.opera,
			identity: "Opera"
		},
		{
			string: navigator.vendor,
			subString: "iCab",
			identity: "iCab"
		},
		{
			string: navigator.vendor,
			subString: "KDE",
			identity: "Konqueror"
		},
		{
			string: navigator.userAgent,
			subString: "Firefox",
			identity: "Firefox"
		},
		{
			string: navigator.vendor,
			subString: "Camino",
			identity: "Camino"
		},
		{		// for newer Netscapes (6+)
			string: navigator.userAgent,
			subString: "Netscape",
			identity: "Netscape"
		},
		{
			string: navigator.userAgent,
			subString: "MSIE",
			identity: "Explorer",
			versionSearch: "MSIE"
		},
		{
			string: navigator.userAgent,
			subString: "Gecko",
			identity: "Mozilla",
			versionSearch: "rv"
		},
		{ 		// for older Netscapes (4-)
			string: navigator.userAgent,
			subString: "Mozilla",
			identity: "Netscape",
			versionSearch: "Mozilla"
		}
	],
	dataOS : [
		{
			string: navigator.platform,
			subString: "Win",
			identity: "Windows"
		},
		{
			string: navigator.platform,
			subString: "Mac",
			identity: "Mac"
		},
		{
			string: navigator.platform,
			subString: "Linux",
			identity: "Linux"
		}
	]

};

BrowserDetect.init();


// Code to be run when page is loaded
$(document).ready(function() {

	// Display please wait message
	$('<div id="pleasewait" style="position:absolute; left:0px; top:250px; height:100%; width:100%;"><img src="' + strPathToCss + '/vam/images/please_wait.gif" width="111" height="106" alt="Please wait" /></div>').prependTo('#www-vam-ac-uk');

	// Hide page
	$("#page").hide();
	$("#about").hide();

	// Add pause and slider controls
    $('<ul class="more" style="float:right"><li class="up" id="sliderWrapper"><li></ul>').insertAfter("#category");
	$("#sliderControl").appendTo("#sliderWrapper");
	$("#fasterCell").html('Slower&nbsp;');
	$("#slowerCell").html('&nbsp;Faster');
	$("#pauseCell").html('<a id="pauseLink" href="#">Pause</a> |&nbsp;&nbsp;<a id="playLink" href="#" class="unselected">Play</a> |&nbsp;&nbsp;');
	$('#pauseLink').click(pause);
	$('#playLink').click(unpause);

	// Change effect of next/previous links
	$('#nextLink').attr("href", "#");
	$('#previousLink').attr("href", "#");
	$('#nextLink').click(next);

	// Grey our previous link
	hidePrevious();

	// Set up random order for image display
	for (var i = 0; i < intObjectCount; i++) {
		arrImages[i] = i + 1;
	}
	arrImages.sort(function () { return (Math.round(Math.random()) - 0.5); });

	// Insert first three img objects
	$.getJSON("object_json.php", {id: arrImages[0]}, function(objImageJSON){
		// Insert first image into DOM and set height of container
		insertImage(0, 0, 'none', objImageJSON);

		$.getJSON("object_json.php", {id: arrImages[1]}, function(objImageJSON){
			// Insert second image into DOM
			insertImage(1, 0, 'none', objImageJSON);
	
			$.getJSON("object_json.php", {id: arrImages[2]}, function(objImageJSON){
				// Insert third image into DOM
				insertImage(2, 0, 'none', objImageJSON);

				// Once all three images are preloaded, fade in first image and start cross-fading
				if (BrowserDetect.browser == "Explorer") {
					var ip = new ImagePreloader(arrImageSources, fadeFirstImage);
				} else {
					fadeFirstImage();
				}
			});
	
		});

	});

});


// Insert image into DOM
function insertImage(intId, floatOpacity, strDisplay, objImageJSON) {
	var objImageWrapper = document.createElement("div");
	$(objImageWrapper).addClass('imageWrapper');

	if (intTitlePosition == 1) $(objImageWrapper).append('<h3 style="display: ' + strDisplay + '">' + objImageJSON.caption + '</h3>');

	var objImage = document.createElement("img");
	$(objImage).attr('src', objImageJSON.src);
	setOpacity(objImage, floatOpacity);
	$(objImage).css('display', strDisplay).attr({width: objImageJSON.width, height: objImageJSON.height, alt: objImageJSON.alt}).appendTo($(objImageWrapper));

	if (intTitlePosition == 0) $(objImageWrapper).append('<h3 style="display: ' + strDisplay + '">' + objImageJSON.caption + '</h3>');

	$(objImageWrapper).append('<p style="display: ' + strDisplay + '">' + objImageJSON.description + '</p>');
	$(objImageWrapper).appendTo('#imageGallery');

	if (objImageJSON.nextsrc) $(document.createElement('img')).attr('src', objImageJSON.nextsrc);

	arrDataLoaded[intId] = true;
	var intHeight = parseInt(objImageJSON.height) + intCaptionHeight + 500;
	arrImageHeights[intId] = intHeight + "px";

	arrImageSources[intId] = objImageJSON.src;
}


// Fade in first image
function fadeFirstImage(arrImages, intImages) {
	// Hide please wait message
	$('#pleasewait').remove();

	// Show page
	$("#page").show();
	$("#about").show();

	// Set fading flag
	boolCurrentlyFading = true;

	// Get array of all img nodes in gallery
	arrImgNodes = $("#imageGallery .imageWrapper img");
	arrHeaderNodes = $("#imageGallery .imageWrapper h3");
	arrCaptionNodes = $("#imageGallery .imageWrapper p");

	// Show caption section
	if (intTitlePosition == 1) {
		arrHeaderNodes[0].style.visibility = "visible";
		arrHeaderNodes[0].style.display = "block";
	} else {
		arrHeaderNodes[0].style.display = "none";
	}
	arrCaptionNodes[0].style.display = "none";

	// Make sure image is visible
	arrImgNodes[0].style.display = "block";

	// Fade in image
	crossFadeSingle();
}


// Fade in one image
function crossFadeSingle() {
	// Calculate new opacity
	floatNextOpacity = arrImgNodes[0].xOpacity + floatFrameSpeed;
	if (floatNextOpacity > 0.99) floatNextOpacity = 0.99;

	// Set new opacity
	setOpacity(arrImgNodes[0], floatNextOpacity);

	if (floatNextOpacity == 0.99) {

		// Fade is finished, so show caption section
		arrHeaderNodes[0].style.visibility = "visible";
		arrHeaderNodes[0].style.display = "block";
		arrCaptionNodes[0].style.display = "block";

		// Set height of container
		$("#imageGallery").css("height", arrImageHeights[0]);

		// Set fading flag
		boolCurrentlyFading = false;

		// Start cross-fading
		objInterval = setInterval("fadeToNext()", intSpeed);

	} else {

		// Otherwise cross-fade again
		setTimeout(crossFadeSingle, intTransitionSpeed);

	}
}


// Pause slideshow
function pause() {
	boolPaused = true;
	clearInterval(objInterval);
	$('#pauseLink').addClass("unselected");
	$('#playLink').removeClass("unselected");

	// Stop default action
	return false;
}


// Restart slideshow
function unpause() {
	boolPaused = false;
	$('#pauseLink').removeClass("unselected");
	$('#playLink').addClass("unselected");
	fadeToNext();
	objInterval = setInterval("fadeToNext()", intSpeed);

	// Stop default action
	return false;
}


// Load next image
function next() {
	// Stop current fade, load next image, and restart fading if not paused
	hideButtons();
	/*alert("next" + boolCurrentlyFading);*/
	clearInterval(objInterval);
	fadeToNext();
	if (!boolPaused) objInterval = setInterval("fadeToNext()", intSpeed);
	// Stop default action
	return false;
}


// Load previous image
function previous() {
	// Stop current fade, load previous image, and restart fading if not paused
	hideButtons();
	/*alert("prev" + boolCurrentlyFading);*/
	clearInterval(objInterval);
	fadeToPrevious();
	if (!boolPaused) objInterval = setInterval("fadeToNext()", intSpeed);
	// Stop default action
	return false;
}


// Grey out previous button
function hidePrevious() {
	$('#previousLink').unbind();
	$('#previousLink').addClass("unselected");
	$('#previousLink').parent().css("background", "url(css/images/back.gif) 0 50% no-repeat");
}


// Grey out next button
function hideNext() {
	$('#nextLink').unbind();
	$('#nextLink').addClass("unselected");
	$('#nextLink').parent().css("background", "url(css/images/forward.gif) 100% 50% no-repeat");
}


// Grey out both buttons
function hideButtons() {
	hidePrevious();
	hideNext();
}

// Show previous button
function showPrevious() {
	$('#previousLink').click(previous);
	$('#previousLink').removeClass("unselected");
	$('#previousLink').parent().css("background", "url(http://www.vam.ac.uk/vam/themes/" + strTheme + "/images/back.gif) 0 50% no-repeat");
}

// Show next button
function showNext() {
	$('#nextLink').click(next);
	$('#nextLink').removeClass("unselected");
	$('#nextLink').parent().css("background", "url(http://www.vam.ac.uk/vam/themes/" + strTheme + "/images/forward.gif) 100% 50% no-repeat");
}

// Show both buttons
function showButtons() {
	showPrevious();
	showNext();
}


// Load next image and fade to it
function fadeToNext() {
	// If we're already fading, don't stack up another one
	if (boolCurrentlyFading) return;

	// Set fading flag
	boolCurrentlyFading = true;

	// If we haven't already loaded this image and there is a next image, load it and fade to it
	if (!boolAllLoaded && !arrDataLoaded[intCurrentImage + 3] && arrImages[intCurrentImage + 3]) {

		$.getJSON("object_json.php", {id: arrImages[intCurrentImage + 3]}, function(objImageJSON){
			// Insert image into DOM
			insertImage(intCurrentImage + 3, 0, 'none', objImageJSON);

			// Get array of all img nodes in gallery
			arrImgNodes = $("#imageGallery .imageWrapper img");
			arrHeaderNodes = $("#imageGallery .imageWrapper h3");
			arrCaptionNodes = $("#imageGallery .imageWrapper p");

			// Work out index for next image, wrapping round if necessary
			intNextImage = arrImgNodes[intCurrentImage + 1] ? intCurrentImage + 1 : 0;
		
			// Hide caption section
			if (intTitlePosition == 1) {
				arrHeaderNodes[intCurrentImage].style.visibility = "hidden";
				arrHeaderNodes[intCurrentImage].style.display = "block";
				arrHeaderNodes[intNextImage].style.visibility = "visible";
				arrHeaderNodes[intNextImage].style.display = "block";
			} else {
				arrHeaderNodes[intCurrentImage].style.visibility = "none";
				arrHeaderNodes[intNextImage].style.display = "none";
			}
			arrCaptionNodes[intCurrentImage].style.display = "none";
			arrCaptionNodes[intNextImage].style.display = "none";

			// Cross-fade to new image
			crossFadeForwards();

		});

	} else {

		// If this is the last image, set boolAllLoaded to true so we don't load any more images
		if (!arrImages[intCurrentImage + 3]) boolAllLoaded = true;

		// Get array of all img nodes in gallery
		arrImgNodes = $("#imageGallery .imageWrapper img");
		arrHeaderNodes = $("#imageGallery .imageWrapper h3");
		arrCaptionNodes = $("#imageGallery .imageWrapper p");

		// Work out index for next image, wrapping round if necessary
		intNextImage = arrImgNodes[intCurrentImage + 1] ? intCurrentImage + 1 : 0;
	
		// Hide caption section
		if (intTitlePosition == 1) {
				arrHeaderNodes[intCurrentImage].style.visibility = "hidden";
				arrHeaderNodes[intCurrentImage].style.display = "block";
				arrHeaderNodes[intNextImage].style.visibility = "visible";
				arrHeaderNodes[intNextImage].style.display = "block";
		} else {
			arrHeaderNodes[intCurrentImage].style.visibility = "none";
			arrHeaderNodes[intNextImage].style.display = "none";
		}
		arrCaptionNodes[intCurrentImage].style.display = "none";
		arrCaptionNodes[intNextImage].style.display = "none";

		// Cross-fade to new image
		crossFadeForwards();

	}
}


// Load previous image and fade to it
function fadeToPrevious() {
	// If we're already fading, don't stack up another one
	if (boolCurrentlyFading) return;

	// Don't fade past the start of the slideshow
	if (intCurrentImage == 0) return;

	// Set fading flag
	boolCurrentlyFading = true;

	// Work out index for previous image, wrapping round if necessary
	intNextImage = intCurrentImage - 1;

	// Hide caption section
	if (intTitlePosition == 1) {
		arrHeaderNodes[intCurrentImage].style.visibility = "hidden";
		arrHeaderNodes[intCurrentImage].style.display = "block";
		arrHeaderNodes[intNextImage].style.visibility = "visible";
		arrHeaderNodes[intNextImage].style.display = "block";
	} else {
		arrHeaderNodes[intCurrentImage].style.visibility = "none";
		arrHeaderNodes[intNextImage].style.display = "none";
	}
	arrCaptionNodes[intCurrentImage].style.display = "none";
	arrCaptionNodes[intNextImage].style.display = "none";

	// Cross-fade to previous image
	crossFadeBackwards();
}


// Cross-fade between two images
function crossFadeForwards() {
	// Calculate new opacities
	floatCurrentOpacity = arrImgNodes[intCurrentImage].xOpacity - floatFrameSpeed;
	floatNextOpacity = arrImgNodes[intNextImage].xOpacity + floatFrameSpeed;
	if (floatNextOpacity > 0.99) floatNextOpacity = 0.99;

	// Make sure next image is visible
	arrImgNodes[intNextImage].style.display = "block";

	// Set new opacities
	setOpacity(arrImgNodes[intCurrentImage], floatCurrentOpacity); 
	setOpacity(arrImgNodes[intNextImage], floatNextOpacity);

	if (floatCurrentOpacity <= 0) {

		// Fade is finished, so hide previous image
		arrImgNodes[intCurrentImage].style.display = "none";

		// And show new caption section
		arrHeaderNodes[intCurrentImage].style.display = "none";
		arrHeaderNodes[intCurrentImage].style.visibility = "visible";
		arrHeaderNodes[intNextImage].style.visibility = "visible";
		arrHeaderNodes[intNextImage].style.display = "block";
		arrCaptionNodes[intNextImage].style.display = "block";

		// Make current image the new image
		intCurrentImage = intNextImage;

		// Set height of container
		$("#imageGallery").css("height", arrImageHeights[intCurrentImage]);

		// If this is the last image, disable the next button, otherwise reinstate next and previous events
		if (intCurrentImage == intObjectCount - 1) {
			hideNext();
		} else {
			showNext();
		}

		showPrevious();

		// Set fading flag
		boolCurrentlyFading = false;
		showButtons()

	} else {

		// Otherwise cross-fade again
		setTimeout(crossFadeForwards, intTransitionSpeed);

	}
}


// Cross-fade between two images
function crossFadeBackwards() {
	// Calculate new opacities
	floatCurrentOpacity = arrImgNodes[intCurrentImage].xOpacity - floatFrameSpeed;
	floatNextOpacity = arrImgNodes[intNextImage].xOpacity + floatFrameSpeed;
	if (floatNextOpacity > 0.99) floatNextOpacity = 0.99;

	// Make sure next image is visible
	arrImgNodes[intNextImage].style.display = "block";

	// Set new opacities
	setOpacity(arrImgNodes[intCurrentImage], floatCurrentOpacity); 
	setOpacity(arrImgNodes[intNextImage], floatNextOpacity);

	if (floatCurrentOpacity <= 0) {

		// Fade is finished, so hide previous image
		arrCaptionNodes[intCurrentImage].style.display = "none";

		// And show new caption section
		arrHeaderNodes[intCurrentImage].style.display = "none";
		arrHeaderNodes[intCurrentImage].style.visibility = "visible";
		arrHeaderNodes[intNextImage].style.visibility = "visible";
		arrHeaderNodes[intNextImage].style.display = "block";
		arrCaptionNodes[intNextImage].style.display = "block";

		// Make current image the new image
		intCurrentImage = intNextImage;

		// Set height of container
		$("#imageGallery").css("height", arrImageHeights[intCurrentImage]);

		// If this is the first image, disable the previous button, otherwise reinstate next and previous events
		if (intCurrentImage == 0) {
			hidePrevious();
		} else {
			showPrevious();
		}

		showNext();

		// Set fading flag
		boolCurrentlyFading = false;
		showButtons()

	} else {

		// Otherwise cross-fade again
		setTimeout(crossFadeBackwards, intTransitionSpeed);

	}
}


// Set opacity in a way that most browsers will understand
function setOpacity(objImgNode, floatOpacity) {
	objImgNode.xOpacity = floatOpacity;
	objImgNode.style.opacity = floatOpacity;
	objImgNode.style.MozOpacity = floatOpacity;
	objImgNode.style.filter = "alpha(opacity=" + (floatOpacity * 100) + ")";
}


// Handler for speed change
function updateSpeed() {
	// Get speed from slider
	intSpeed = 11000 - $("#sliderValue").val();

	// If paused, clear old interval and set new one
	if (!boolPaused) {
		clearInterval(objInterval);
		objInterval = setInterval("fadeToNext()", intSpeed);
	}
}


// Image preloader code
function ImagePreloader(arrImages, fnCallBack) {
   // store the call-back
   this.callBack = fnCallBack;
 
   // initialize internal state.
   this.nLoaded = 0;
   this.nProcessed = 0;
   this.aImages = new Array;
 
   // record the number of images.
   this.nImages = arrImages.length;
 
   // for each image, call preload()
   for ( var i = 0; i < arrImages.length; i++ ) 
      this.preload(arrImages[i]);
}

ImagePreloader.prototype.preload = function(image) {
   // create new Image object and add to array
   var oImage = new Image;
   this.aImages.push(oImage);
   
   // set up event handlers for the Image object
   oImage.onload = ImagePreloader.prototype.onload;
   oImage.onerror = ImagePreloader.prototype.onerror;
   oImage.onabort = ImagePreloader.prototype.onabort;
   
   // assign pointer back to this.
   oImage.oImagePreloader = this;
   oImage.bLoaded = false;
   
   // assign the .src property of the Image object
   oImage.src = image;
}

ImagePreloader.prototype.onComplete = function() {
   this.nProcessed++;
   if ( this.nProcessed == this.nImages )
   {
      this.callBack(this.aImages, this.nLoaded);
   }
}

ImagePreloader.prototype.onload = function() {
   this.bLoaded = true;
   this.oImagePreloader.nLoaded++;
   this.oImagePreloader.onComplete();
}

ImagePreloader.prototype.onerror = function() {
   this.bError = true;
   this.oImagePreloader.onComplete();
}

ImagePreloader.prototype.onabort = function() {
   this.bAbort = true;
   this.oImagePreloader.onComplete();
}


