function Exhibitionist_slideshowController(){
	this.playing = false;
	this.exhibitionist;
	this.imageCount = 0;
	this.currentImage = 0;
	this.transitionController;
	this.changeImageDelay = 4000;
	this.galleryEffectSpeedStep = 0.01;
	this.init = function(exhibitionist){
		this.exhibitionist = exhibitionist;
		this.exhibitionist.trace("Slideshow: Begining initalisation");
		this.changeImageDelay = exhibitionist.optionsArray['swapImageSpeed'];
		this.imageCount = this.exhibitionist.imageCount;
		
		this.transitionController = new Exhibitionist_transitionController;
		this.exhibitionist.trace("Slideshow: Initalising transition ontroller");
		this.transitionController.init(exhibitionist);
	}
	this.start = function(){
		this.exhibitionist.trace("Slideshow: Starting");
		this.transitionController.changeImage(this.exhibitionist.imagesArray[this.currentImage]);
		this.playing = true;
		setTimeout(function(object){
					return function(){
						object.nextImage();
					}
		}(this),this.changeImageDelay);
		
	}
	this.startOn = function(number){
		this.currentImage = number;
		this.start();
	}
	this.stop = function(){
		this.exhibitionist.trace("Slideshow: Stopping");
		this.playing = false;
	}
	this.hide = function(){
		this.stop();
		this.transitionController.changeImage(null);
	}
	this.nextImage = function(){
		if (this.playing == true){
			lastImage = this.currentImage;
			this.currentImage++;
			if (this.currentImage >= this.imageCount){
				this.currentImage = 0;
			}
			this.exhibitionist.trace("Slideshow: Changing to image "+this.currentImage);
			this.transitionController.changeImage(this.exhibitionist.imagesArray[this.currentImage]);
			setTimeout(function(object){
				return function(){
					object.nextImage();
				}
			}(this),this.changeImageDelay);
		}
	}
}


function Exhibitionist_compactCaptionController(){
	this.exhibitionist;
	this.imageCount = 0;
	this.currentImage = 0;
	this.transitionController;
	this.changeImageDelay = 4000;
	this.galleryEffectSpeedStep = 0.01;
	this.init = function(exhibitionist){
		this.exhibitionist = exhibitionist;
		this.exhibitionist.trace("Compact Caption: Begining initalisation");
		this.changeImageDelay = exhibitionist.gallerySwapImageSpeed;
		this.imageCount = exhibitionist.imageCount;
		this.transitionController = new Exhibitionist_transitionController;
		this.exhibitionist.trace("Compact Caption: Initalising Transition Controller");
		this.transitionController.init(exhibitionist);
		//modify the image objects captions with the next and back buttons
		this.exhibitionist.trace("Compact Caption: Modifing image captions");
		for (imageObjectNum in this.exhibitionist.imagesArray){
			this.exhibitionist.trace("Compact Caption: Modifing image caption from array "+imageObjectNum);
			var imageObject = exhibitionist.imagesArray[imageObjectNum];
			imageObject.caption.innerHTML = "";
			var captionContainer = document.createElement(exhibitionist.optionsArray['imageCaptionObjectType']);
			captionContainer.setAttribute('class', exhibitionist.optionsArray['imageCaptionObjectClass']);
			var captionText = document.createTextNode(imageObject.caption.text);
			
			var back = document.createElement('a');
			var backText = document.createTextNode(parseHTMLText("<"));
			back.appendChild(backText);
			back.href="#";
			back.self = this;
			back.onclick = function (){
				this.self.lastImage();
				return false;
			}
			
			var next = document.createElement('a');
			var nextText = document.createTextNode(parseHTMLText(">"));
			next.appendChild(nextText);
			next.href="#";
			next.self = this;
			next.onclick = function(){
				this.self.nextImage();
				return false;
			}
			imageObject.imageClickHolder.self = this;
			imageObject.imageClickHolder.onclick = function(){
				this.self.nextImage();
				return false;
			}
			var pageNumberTextNode = document.createTextNode((parseInt(imageObjectNum) + 1) + " of " + this.imageCount);
			var spacer = document.createTextNode(" ");
			
			
			captionContainer.appendChild(back);
			captionContainer.appendChild(pageNumberTextNode);
			captionContainer.appendChild(next);
			captionContainer.appendChild(spacer);
			if (exhibitionist.optionsArray['imageCaptionEnable']){
				captionContainer.appendChild(captionText);
			}
			
			exhibitionist.container.appendChild(captionContainer);
			imageObject.caption.displayHeight = captionContainer.offsetHeight;
			exhibitionist.container.removeChild(captionContainer);
			
			imageObject.caption.appendChild(captionContainer);
			
		}
	}
	this.start = function(){
		this.exhibitionist.trace("Compact Caption: Being Started");
		this.transitionController.changeImage(this.exhibitionist.imagesArray[this.currentImage]);
	}
	this.startOn = function(number){
		this.exhibitionist.trace("Compact Caption: Being Started On "+number);
		this.transitionController.changeImage(this.exhibitionist.imagesArray[number]);
		this.currentImage = number;
	}
	this.nextImage = function(){
		this.exhibitionist.trace("Compact Caption: Going to next image");
		this.currentImage++;
		if (this.currentImage >= this.imageCount){
			this.currentImage = 0;
		}
		this.transitionController.changeImage(this.exhibitionist.imagesArray[this.currentImage]);
	}
	this.lastImage = function(){
		this.exhibitionist.trace("Compact Caption: Going to previous image");
		this.currentImage--;
		if (this.currentImage == -1){
			this.currentImage = (this.imageCount - 1);
		}
		this.transitionController.changeImage(this.exhibitionist.imagesArray[this.currentImage]);
	}
	this.hide = function(){
		this.transitionController.changeImage(null);
	}
	
}


function Exhibitionist_thumbnailCaptionController(){
	this.exhibitionist;
	this.thumbnailsRowWidth = 0;
	this.thumbnailsRowHeight = 0;
	this.stillSliding = false;
	this.clickFunction = function(clickedThumbnail){
		alert("secondary function");
	}
	this.init = function(exhibitionist){
		this.exhibitionist = exhibitionist;
		this.exhibitionist.trace("Inline Thumbnail: Begining initalisation");
		this.imageCount = this.exhibitionist.imageCount;
		
		this.transitionController = new Exhibitionist_transitionController;
		this.exhibitionist.trace("Inline Thumbnail: Initalising Transition Controller");
		this.transitionController.init(exhibitionist);
		
		this.thumbnailMask = document.createElement('div');
		this.thumbnailMask.id = "thumbnailMask";
		
		this.thumbnailHolder = document.createElement('div');
		this.thumbnailHolder.id = "Exhibitionist_thumbnailHolder";
		this.thumbnailHolder.style.height = this.thumbnailMask.style.height;
		this.thumbnailHolder.style.position = "relative";
		this.thumbnailHolder.totalWidth = 0;
		
		this.exhibitionist.trace("Inline Thumbnail: Adding thumbnails");
		var thumbnailLeftOffset = 0;
		for (imageObjectNum in this.exhibitionist.imagesArray){
			this.exhibitionist.trace("Inline Thumbnail: Adding thumbnail for image "+imageObjectNum);
			var imageObject = exhibitionist.imagesArray[imageObjectNum];
			
			var thumbnailObject = imageObject.thumbnail.make(this.thumbnailPadding,undefined,this.exhibitionist.optionsArray['thumbnailCenteringNoX'],this.exhibitionist.optionsArray['thumbnailCenteringNoY']);
			this.thumbnailsRowWidth = this.thumbnailsRowWidth + thumbnailObject.totalWidth;
			if (thumbnailObject.totalHeight > this.thumbnailsRowHeight){
				this.thumbnailsRowHeight = thumbnailObject.totalHeight;
			}
			
			thumbnailObject.thumbnail.number = imageObjectNum;
			thumbnailObject.thumbnail.self = this;
			thumbnailObject.thumbnail.leftOffset = thumbnailLeftOffset;
			
			thumbnailLeftOffset+= thumbnailObject.totalWidth;
			thumbnailObject.thumbnail.onclick = function(){
				if (this.self.stillSliding == false){
					if (this.self.transitionController.waitingThreads == 0){
						this.self.exhibitionist.trace("Inline Thumbnail: Changing to image "+this.number);
						this.self.transitionController.changeImage(this.self.exhibitionist.imagesArray[this.number]);
						this.self.clickFunction(this);
					}else{
						this.self.exhibitionist.trace("Inline Thumbnail: Can Not Change, waiting for "+this.self.transitionController.waitingThreads+" threads");
					}
				}else{
					this.self.exhibitionist.trace("Inline Thumbnail: Can Not Change, Waiting for last thumbnail slide to complete.");
				}
				return false;
			}
			this.thumbnailHolder.appendChild(thumbnailObject.thumbnail);
			//make image click go to nect image
			imageObject.imageClickHolder.nextImageNumber = parseInt(imageObjectNum) + 1;
			if (imageObject.imageClickHolder.nextImageNumber >= exhibitionist.imagesArray.length){
				imageObject.imageClickHolder.nextImageNumber = 0;
			}
			
			imageObject.imageClickHolder.self = this;
			imageObject.imageClickHolder.onclick = function(){
				if (this.self.stillSliding == false){
					if (this.self.transitionController.waitingThreads == 0){
						var imageObject = exhibitionist.imagesArray[this.nextImageNumber];
						this.self.exhibitionist.trace("Inline Thumbnail: Changing to image "+this.nextImageNumber);
						this.self.transitionController.changeImage(imageObject);
						this.self.clickFunction(imageObject.thumbnail.thumbnail);
					}else{	
						this.self.exhibitionist.trace("Inline Thumbnail: Can Not Change, waiting for "+this.self.transitionController.waitingThreads+" threads");
					}
				}else{
					this.self.exhibitionist.trace("Inline Thumbnail: Can Not Change, Waiting for last thumbnail slide to complete.");
				}
				return false;
			}
			
			
		}
		var inlineScrollMode = "scrollToCenter";
		switch(inlineScrollMode){
			case("basic"):
				this.thumbnailMask.style.position = "relative";
				this.thumbnailMask.style.overflowX = "scroll";
				this.thumbnailMask.style.overflowY = "hidden";
				this.thumbnailHolder.style.width = this.thumbnailsRowWidth+"px";
				this.thumbnailHolder.style.height = this.thumbnailsRowHeight+"px";
				this.thumbnailMask.style.height = (this.thumbnailsRowHeight + 16) + "px";
				this.thumbnailMask.appendChild(this.thumbnailHolder);
			break;
			case("scrollToCenter"):
				this.thumbnailMask.style.position = "relative";
				this.thumbnailMask.style.overflow = "hidden";
				this.thumbnailMask.style.height = this.thumbnailsRowHeight+"px";
				
				this.thumbnailHolder.style.height = this.thumbnailsRowHeight+"px";
				this.thumbnailHolder.style.width = this.thumbnailsRowWidth+"px";
				this.thumbnailHolder.currentLeft = 0;
				this.thumbnailMask.appendChild(this.thumbnailHolder);
				this.clickFunction = function(clickedThumbnail){
					var maskCenter = (0.5 * this.thumbnailMask.offsetWidth) - (0.5 * clickedThumbnail.parent.totalWidth);
					var thumbnailHolderLeft = (-clickedThumbnail.leftOffset + maskCenter);
					if (thumbnailHolderLeft > 0){
						var newThumbnailHolderLeft = 0;
					}else if(-thumbnailHolderLeft > (this.thumbnailsRowWidth - this.thumbnailMask.offsetWidth)){
						var newThumbnailHolderLeft = -(this.thumbnailsRowWidth - this.thumbnailMask.offsetWidth);
					}else{
						newThumbnailHolderLeft = thumbnailHolderLeft;
					}
					this.slideObjectTo(this,newThumbnailHolderLeft,this.thumbnailHolder);
					//this.thumbnailHolder.style.left = newThumbnailHolderLeft+"px";
				}
			break;
			
		}
	}
	this.gotoImage = function(imageNumber){
		var clickedThumbnail = this.exhibitionist.imagesArray[imageNumber].thumbnail;
		//alert("function repalced "+imageNumber);
		this.clickFunction(clickedThumbnail);
		
	}
	this.slideObjectTo = function(object,left,moveObject){
		var reschedule = false;
		this.stillSliding = true;
		var accelerator = 3;
		accelerator = accelerator * accelerator;
		if (left > moveObject.currentLeft){
			var step = ((left - moveObject.currentLeft) / accelerator) + 1
			moveObject.currentLeft+=step;
			if (moveObject.currentLeft < left){
				reschedule = true;
			}
		}else if (left < moveObject.currentLeft){
			var step = -((left - moveObject.currentLeft) / accelerator) + 1
			moveObject.currentLeft-=step;
			if (moveObject.currentLeft > left){
				reschedule = true;
			}
		}else{
			reschedule = false;
			moveObject.currentLeft = left;
		}
		
		moveObject.style.left = moveObject.currentLeft+"px";
		if (reschedule == true){
			setTimeout(function(object,left,moveObject){
						return function(){
							object.slideObjectTo(object,left,moveObject);
						}
			}(object,left,moveObject),30);
		}else{
			moveObject.currentLeft = left;
			moveObject.style.left = moveObject.currentLeft+"px";
			this.stillSliding = false;
		}
	}
	this.start = function(){
		this.exhibitionist.container.appendChild(this.thumbnailMask);
		this.exhibitionist.trace("Inline Thumbnail: Starting");
		this.transitionController.changeImage(this.exhibitionist.imagesArray[0]);
	}
	this.startOn = function(number){
		this.exhibitionist.container.appendChild(this.thumbnailMask);
		this.exhibitionist.trace("Inline Thumbnail: Starting On "+number);
		if (this.transitionController.stillWorking == false){
				this.exhibitionist.trace("Inline Thumbnail: Changing to image "+number);
				this.transitionController.changeImage(this.exhibitionist.imagesArray[number]);
				this.clickFunction(this.exhibitionist.imagesArray[number].thumbnail.thumbnail);
		}
	}
	this.hide = function(){
		this.exhibitionist.trace("Inline Thumbnail: Hiding");
		this.transitionController.changeImage(null);
		this.exhibitionist.container.removeChild(this.thumbnailMask);
	}
}

function Exhibitionist_gridThumbnailController(){
	this.exhibitionist;
	this.thumbsNumber = 0;
	this.transitionController;
	this.thumbnailImageObject;
	this.gridModePadding = 5;
	this.gridModeCentering = false;
	this.init = function(exhibitionist){
		this.exhibitionist = exhibitionist;
		this.exhibitionist.trace("Grid Thumbnail: Begining initalisation");
		this.gridModeCentering = this.exhibitionist.optionsArray['thumbnailCentering'];
		this.gridModePadding = this.exhibitionist.optionsArray['thumbnailPadding'];
		this.imageCount = this.exhibitionist.imageCount;
		this.transitionController = new Exhibitionist_transitionController;
		this.transitionController.init(exhibitionist);
		
		this.thumbnailHolder = document.createElement('div');
		this.thumbnailHolder.id = "thumbnailHolder";
		if (this.exhibitionist.optionsArray['gridWithUseImageGrid'] == true){
			this.thumbnailHolder.style.width = this.exhibitionist.widestWidth+"px";
		}else{
			this.thumbnailHolder.style.width = this.exhibitionist.optionsArray['gridWidthGrid']+"px";
		}
		
		
		// GRID USING INCORRECT THUMBNAIL CENTERING!!!!
		// SHOULD USE THE IMAGEOBJECT CLASS FOR CREATION AND CENTERING
		this.exhibitionist.trace("Grid Thumbnail: Adding Thumbnails");
		for (imageObjectNum in this.exhibitionist.imagesArray){
			this.exhibitionist.trace("Grid Thumbnail: Adding thumbnail "+imageObjectNum);
			var imageObject = exhibitionist.imagesArray[imageObjectNum];
			var thumbnailContainer = document.createElement('a');
			thumbnailContainer.style.display = "inline";
			var thWidth = imageObject.thumbnailWidth;
			var thHeight = imageObject.thumbnailHeight;
			if (thWidth > thHeight){
				var paddingTopBottom = ((thWidth - thHeight) / 2);
				var paddingLeftRight = 0;
			}else{
				var paddingLeftRight = ((thHeight - thWidth) / 2);
				var paddingTopBottom = 0;
			}
			
			thumbnailContainer.href = "#";
			thumbnailContainer.number = imageObjectNum;
			thumbnailContainer.self = this;
			thumbnailContainer.onclick = function(){
				this.self.transitionController.changeImage(this.self.exhibitionist.imagesArray[this.number]);
				this.self.exhibitionist.trace("Grid Thumbnail: Changing to image "+this.number);
				return false;
			}
			
			var thumbnail = new Image();
			thumbnail.src = imageObject.thumbnailURL;
			if (this.gridModeCentering == true){
				thumbnail.style.margin = paddingTopBottom+"px "+paddingLeftRight+"px "+paddingTopBottom+"px "+paddingLeftRight+"px";
			}
			thumbnail.style.padding = this.gridModePadding + "px";
			
			thumbnailContainer.appendChild(thumbnail);
			this.thumbnailHolder.appendChild(thumbnailContainer);
		}
		
		this.thumbsNumber = imageObjectNum + 1;
		this.thumbnailImageObject = new Exhibitionist_imageObject;
		this.thumbnailImageObject.type = "psudo";
		this.thumbnailImageObject.initUsingObject(this.thumbnailHolder);
		this.exhibitionist.imagesArray[this.thumbsNumber] = this.thumbnailImageObject;
		for (imageObjectNum in this.exhibitionist.imagesArray){
			var imageObject = exhibitionist.imagesArray[imageObjectNum];
			if (imageObject != this.thumbnailImageObject){
				imageObject.holder.self = this;
				imageObject.holder.onclick = function(){
					this.self.transitionController.changeImage(this.self.thumbnailImageObject);
					return false;
				}
			}
		}
		
	}
	this.start = function(){
		this.exhibitionist.trace("Grid Thumbnail: Starting");
		this.transitionController.changeImage(this.thumbnailImageObject);
	}
	this.startOn = function(number){
		this.exhibitionist.trace("Grid Thumbnail: Starting");
		this.transitionController.changeImage(this.exhibitionist.imagesArray[number]);
	}
	this.hide = function(){
		this.exhibitionist.trace("Grid Thumbnail: Hiding");
		this.transitionController.changeImage(null);
	}
}


function Exhibitionist_infoBarNavigator(){
	//class variable definitions
	this.exhibitionist;
	this.imagePosition;
	this.infoBarHolder = document.createElement("div");
	this.infoBarHolder.id = "infoBarHolder";
	this.infoBarHolder.name = "infoBarHolder";
	//class funtions
	this.init = function(exhibitionist){
		this.transitionController = new Exhibitionist_transitionController;
		this.transitionController.init(exhibitionist);
		
		this.exhibitionist = exhibitionist;
		this.exhibitionist.trace("Info Bar: Begining initalisation");
		
		for (imageObjectNum in this.exhibitionist.imagesArray){
			var currentImageObject = this.exhibitionist.imagesArray[imageObjectNum];
			currentImageObject.imageClickHolder.nextNumber = parseInt(imageObjectNum) + 1;
			
			if (currentImageObject.imageClickHolder.nextNumber >= this.exhibitionist.imagesArray.length){
				currentImageObject.imageClickHolder.nextNumber = 0;
			}
			currentImageObject.imageClickHolder.parent = this;
			currentImageObject.imageClickHolder.onclick = function(){
				this.parent.gotoImage(this.nextNumber);
				return false;
			}
			
			currentImageObject.removeTitle();
			currentImageObject.removeCaption();
			
			
			//build the info objet....
			this.exhibitionist.trace("Info Bar: Image:"+imageObjectNum+": Building Info Object");
			for (var i=1;i <= 7;i++){
				this.exhibitionist.trace("Info Bar: Image:"+imageObjectNum+": Position = "+this.exhibitionist.optionsArray['infoBarElement'+i+"Position"]);
				switch (this.exhibitionist.optionsArray['infoBarElement'+i+"Position"]){
					case "imageLeft":
						var currentInfoBarHolder = currentImageObject.leftElement;
					break;
					case "imageRight":
						var currentInfoBarHolder = currentImageObject.rightElement;
					break;
					case "imageBottom":
						var currentInfoBarHolder = currentImageObject.belowElement;
					break;
					case "imageTop":
						var currentInfoBarHolder = currentImageObject.aboveElement;
					break;
			}
				var currentType = this.exhibitionist.optionsArray['infoBarElement'+i];
				switch (currentType){
					case "title":
						this.exhibitionist.trace("Info Bar: Image:"+imageObjectNum+": Building Info Object Position"+i+" = Title");
						var titleHolder = document.createElement("div");
						titleHolder.id = "infoBarTitle";
						titleHolder.innerHTML = titleHolder.innerHTML + currentImageObject.titleText;
						currentInfoBarHolder.appendChild(titleHolder);
					break;
					case "last":
						this.exhibitionist.trace("Info Bar: Image:"+imageObjectNum+": Building Info Object Position"+i+" = Last Button");
						var lastButton = document.createElement("a");
						lastButton.setAttribute('href', "#");
						lastButton.appendChild(document.createTextNode("<"));
						lastButton.id = "infoBarLastbutton";
						lastButton.style.display = "inline";
						lastButton.parent = this;
						lastButton.number = imageObjectNum;
						lastButton.onclick = function(){
							var last = parseInt(this.number) - 1;
							if (last == -1){
								last = this.parent.exhibitionist.imagesArray.length - 1;
							}
							this.parent.gotoImage(last);
							return false;
						}
						currentInfoBarHolder.appendChild(lastButton);
					break;
					case "next":
						this.exhibitionist.trace("Info Bar: Image:"+imageObjectNum+": Building Info Object Position"+i+" = Next Button");
						var nextButton = document.createElement("a");
						nextButton.setAttribute('href', "#");
						nextButton.appendChild(document.createTextNode(">"));
						nextButton.id = "infoBarNextbutton";
						nextButton.parent = this;
						nextButton.number = imageObjectNum;
						nextButton.onclick = function(){
							var next = parseInt(this.number) + 1;
							if (next > (this.parent.exhibitionist.imagesArray.length - 1)){
								next = 0;
							}
							this.parent.gotoImage(next);
							return false;
						}
						currentInfoBarHolder.appendChild(nextButton);
					break;
					case "number":
						this.exhibitionist.trace("Info Bar: Image:"+imageObjectNum+": Building Info Object Position"+i+" = Image Number");
						var numberElement = document.createElement("div");
						numberElement.id = "infoBarImageNumber";
						if (imageObjectNum < 9){
							var text = " "+ (parseInt(imageObjectNum) + 1);
						}else{
							var text = (parseInt(imageObjectNum) + 1);
						}
						numberElement.innerHTML = numberElement.innerHTML+text+" of "+this.exhibitionist.imagesArray.length;
						currentInfoBarHolder.appendChild(numberElement);
					break;
					case "caption":
						this.exhibitionist.trace("Info Bar: Image:"+imageObjectNum+": Building Info Object Position"+i+" = Caption");
						var captionHolder = document.createElement("div");
						captionHolder.id = "infoBarCaption";
						captionHolder.innerHTML = captionHolder.innerHTML + currentImageObject.captionText;
						currentInfoBarHolder.appendChild(captionHolder);
					break;
					case "description":
						this.exhibitionist.trace("Info Bar: Image:"+imageObjectNum+": Building Info Object Position"+i+" = Description");
						var descriptionHolder = document.createElement("div");
						var string = currentImageObject.descriptionText;
						descriptionHolder.id = "infoBarDescription";
						descriptionHolder.innerHTML = descriptionHolder.innerHTML + string;
						currentInfoBarHolder.appendChild(descriptionHolder);
					break;
				}
			}
		this.exhibitionist.trace("Info Bar: Ending initalisation");
		}
	}
	this.gotoImage = function(number){
		this.transitionController.changeImage(this.exhibitionist.imagesArray[number]);
	}
	this.start = function(){
		this.exhibitionist.trace("Info Bar: Starting");
		this.transitionController.changeImage(this.exhibitionist.imagesArray[0]);
		this.imagePosition = 0;
	}
	this.startOn = function(number){
		this.exhibitionist.trace("Info Bar: Starting at "+number);
		this.transitionController.changeImage(this.exhibitionist.imagesArray[number]);
		this.imagePosition = number;
	}
	this.hide = function(){
		this.exhibitionist.trace("Info Bar: Removing");
		this.transitionController.changeImage(null);
	}
}