
function SlideShow(descriptor)
{
	var imageImageType = "image";
	var thumbnailImageType = "thumbnail";

	this.descriptor = descriptor;
	this._hasBuiltIndex = false;
	this.currentIndex = -1;
	this.imageIsFinishedLoading = false;
	this._currentImage = null;

	this.setup = function() {
		if (!this._hasBuiltIndex) {
			this._buildIndex();
		}
	}

	this.length = function() {
		return this.descriptor.slides.length;
	}

	this.currentSlide = function() {
		return this.descriptor.slides[this.currentIndex];
	}

	this.nextSlide = function() {
		this.currentIndex = this.currentIndex + 1;
		if (this.currentIndex >= this.length()) {
			this.currentIndex = -1;
		}
	    if (this.currentIndex >= 0) {
	        window.document.location = this._getCurrentFilename() + "?slideIndex=" + this.currentIndex;
    	} else {
        	window.document.location = this._getCurrentFilename();
	    }
	}

	this.previousSlide = function() {
		this.currentIndex = this.currentIndex - 1;
		if (this.currentIndex < -1) {
			this.currentIndex = this.length() - 1;
		}
    	if (this.currentIndex >= 0) {
	        window.document.location = this._getCurrentFilename() + "?slideIndex=" + this.currentIndex;
	    } else {
    	    window.document.location = this._getCurrentFilename();
	    }
	}

	this._buildIndex = function() {
		var galleryIndex = document.getElementById("gallery_index");
		var galleryTable = document.createElement('table');
		galleryTable.className = "galleryTable";

		var galleryTableBody = document.createElement('tbody');
		galleryTable.appendChild(galleryTableBody);

		var galleryRow;
		var slides = this.descriptor.slides;
		var slideCount = slides.length;
		var slideIndex;
		var columnCount = this.descriptor.indexNumColumns;
		if (!columnCount || columnCount == 0) {
			columnCount = 4;
		}
		for (slideIndex = 0; slideIndex < slideCount; slideIndex++) {
			if (slideIndex % columnCount == 0) {
				galleryRow = document.createElement('tr');
				galleryRow.className = "galleryRow";
				galleryTableBody.appendChild(galleryRow);
			}

			var galleryCell = document.createElement('td');
			galleryCell.className = "galleryColumn";
			galleryRow.appendChild(galleryCell);

			var slide = slides[slideIndex];

			var galleryThumbnailLink = document.createElement('a');
			galleryThumbnailLink.href = this._getCurrentFilename() + "?slideIndex=" + slideIndex;
			galleryCell.appendChild(galleryThumbnailLink);

			var galleryThumbnail = document.createElement('img');
			galleryThumbnail.className = "galleryThumbnail";
			var path = this._thumbnailHrefForSlide(slide);
			galleryThumbnail.src = path;
			galleryThumbnail.alt = slide.caption;
			galleryThumbnailLink.appendChild(galleryThumbnail);
		}

		galleryIndex.appendChild(galleryTable);
	}

	this.goToSlideAtIndex = function(newIndex) {
		var newImage;
		var slide;
		var fullPath;
		var element;

		if (newIndex >= this.length()) {
			newIndex = -1;
		}
		if (newIndex < -1) {
			newIndex = -1;
		}

		if (newIndex == -1) {
			this.showGalleryIndexArea();
			return;
		} else {
			this.showGalleryPhotoArea();
		}

		this.currentIndex = newIndex;
		slide = this.descriptor.slides[this.currentIndex];

		element = document.getElementById("status_text");
		if (element != null) {
			element.innerHTML = (this.currentIndex + 1) + " of " + this.length();
		}

		fullPath = this._imageHrefForSlide(slide);

		element = document.getElementById("screen");
		if (element != null) {
			// I would just change the src of the old img element, but for some reason at least some browsers won't always resize the img element correctly based on the new image src. (The main time I would see this was in OmniWeb and Safari when switching from a square image to a portrait-oriented image. <shrug>) Replacing the img node resolves the issue. I make an attempt to support browsers that don't support the DOM-modification stuff, but I don't know how likely that is or if my code actually works - I don't have anything to test against.
			this.imageIsFinishedLoading = false;
			var callbackThis = this;

			var loadCallback = function() { callbackThis.finishedLoadingImage(); }
			this._currentImage = new Image();
			this._currentImage.onload = loadCallback;
			this._currentImage.onerror = loadCallback;
			this._currentImage.onabort = loadCallback;
			this._currentImage.src = fullPath;

			var timeoutCallback = function() { callbackThis.updateCaption(); }
			setTimeout('timeoutCallback()', 50);

			if (document.createElement == null) {
				element.src = fullPath;
				element.title = slide.href;
			} else {
				var oldElement = element;
				element = document.createElement('img');
				element.id = oldElement.id;
				element.className = "galleryImage";
				element.src = fullPath;
				element.title = slide.href;
				var parentNode = oldElement.parentNode;
				parentNode.replaceChild(element, oldElement);
			}
		}

		newIndex = this.currentIndex + 1;
		if (newIndex < this.length()) {
			fullPath = this._imageHrefForSlide(this.descriptor.slides[newIndex]);
			var preloadImage = new Image();
			preloadImage.src = fullPath;
		}
	}

	this._hrefForSlide = function(slide, imageType) {
		var href = this.descriptor.baseHref;
		if (href == null) {
			href = "";
		}

		var temp = slide.baseHref;
		if (temp != null && temp.length > 0) {
			if (href.length > 0) {
				href = href + "/" + temp;
			} else {
				href = temp;
			}
		}

		if (imageType == imageImageType) {
			temp = this.descriptor.imageHref;
		} else if (imageType == thumbnailImageType) {
			temp = this.descriptor.thumbnailHref;
		} else if (imageType != null) {
			alert("Unrecognized image type: " + imageType);
		}
		if (temp != null && temp.length > 0) {
			if (href.length > 0) {
				href = href + "/" + temp;
			} else {
				href = temp;
			}
		}

		if (href.length > 0) {
			href = href + "/" + slide.href;
		} else {
			href = slide.href;
		}

		return href;
	}

	this._thumbnailHrefForSlide = function(slide) {
		return this._hrefForSlide(slide, thumbnailImageType);
	}

	this._imageHrefForSlide = function(slide) {
		return this._hrefForSlide(slide, imageImageType);
	}

	this.finishedLoadingImage = function() {
		this.imageIsFinishedLoading = true;
		this.updateCaption();
	}

	this.updateCaption = function() {
		var caption = this.currentSlide().caption;
		if ((this._currentImage != null) && !this._currentImage.complete && !this.imageIsFinishedLoading) {
			this.setCaption("...loading...");
			var callbackThis = this;
			var timeoutCallback = function() { alert("test2: " + callbackThis); callbackThis.updateCaption(); }
			setTimeout('timeoutCallback()', 100);

		} else {
			this.imageIsFinishedLoading = true;
			this.setCaption(caption);
		}
	}

	this.setCaption = function(caption) {
		// innerText is IE extension; works in OmniWeb and Safari, but not in FireFox
		// textContent works in FireFox, but doesn't work in OmniWeb
		var element = document.getElementById("caption");
		if (element != null) {
			element.innerHTML = caption;
		}
	}

	this._getCurrentFilename = function() {
		var currentHref = unescape(location.href);
		var startingIndex = currentHref.lastIndexOf("/") + 1;
		var endingIndex = currentHref.indexOf("?");
		if (endingIndex < startingIndex) {
			endingIndex = currentHref.length;
		}
		var filename = currentHref.substring(startingIndex, endingIndex);
		return filename;
	}

	this.showGalleryIndexArea = function() {
		var element;
		element = document.getElementById("gallery_index");
		element.style.display = "";
		element = document.getElementById("other_galleries");
		if (element != null) {
			element.style.display = "";
		}
		element = document.getElementById("gallery_photo");
		element.style.display = "none";
	}

	this.showGalleryPhotoArea = function() {
		var element;
		element = document.getElementById("gallery_photo");
		element.style.display = "";
		element = document.getElementById("gallery_index");
		element.style.display = "none";
		element = document.getElementById("other_galleries");
		if (element != null) {
			element.style.display = "none";
		}
	}

	this.goToRequestedGalleryPage = function(slideshow) {
		var slideIndex = parseInt(getURLParameter(window.document.location, "slideIndex", "-1"));
		if (slideIndex == -1) {
			this.showGalleryIndexArea();
			element = document.getElementById("status_text");
			if (element != null) {
				element.innerHTML = this.length() + " photos";
			}

			if (! this._hasBuiltIndex) {
				this._buildIndex();
			}

		} else {
//			this.showGalleryPhotoArea();
			this.goToSlideAtIndex(slideIndex);
		}
	}
}

