
	/**
	 * CustomerGardens is the client side logic behind customer_gardens
	 * @param {Object} options
	 * options["url"] = the AJAX service to interface with
	 * options["main_image"] = The ID of the main img tag for an image
	 * options["image_title"] = The ID of the image title div
	 * options["customer_name"] = The ID of the customer name div
	 * options["image_desc"] = The ID of the image description div
	 * options["next_page_btn"] = The ID of the next page button
	 * options["prev_page_btn"] = The ID of the prev page button
	 * options["next_img_btn"] = The ID of the next image button
	 * options["prev_img_btn"] = The ID of the prev image button
	 * options["image_select_bar"] = The ID of the Image select bar
	 * options["images_per_page"] = How many images per page?
	 * options["image_loading"] = The URL of the loading image
	 */
	function CustomerGardens(options)
	{		
		this.init(options)
		return this;
	}
	
	/**
	 * Utility function
	 */
	function IsNumeric(input)
	{
	   return (input - 0) == input && input.length > 0;
	}
	
	$.extend(CustomerGardens.prototype, {
		
		ImagePages 		: [],
		ToAdd			: [],
		Loaded			: false,
		Elements		: null,
		CurrentPage		: 1,
		CurrentImage	: 1,
		InitalImageId	: null,
		
		/**
		 * Inits the customer gallery
		 */
		init : function(options)
		{
			var that = this;
			this.MaxPages = options.pages;
			this.LoadedPages = 4;
						
			$(document).ready(function(){
				
				// add in our sweet historyness
				$.history.init(function(hash){that.navEvent(hash)});
				
				// Get all of our elements
				that.Options = options;
				that.Elements = {
					MainImage		: $("#" + options.main_image),
					ImageTitle		: $("#" + options.image_title),
					CustomerName	: $("#" + options.customer_name),
					ImageDesc		: $("#" + options.image_desc),
					NextPage		: $("#" + options.next_page_btn),
					PrevPage		: $("#" + options.prev_page_btn),
					NextImg			: $("#" + options.next_img_btn),
					PrevImg			: $("#" + options.prev_img_btn),
					ImgSelect		: $("#" + options.image_select_bar)
				};
				
				that.Loaded = true;
				
				// Add all queued images
				for (var i = 0; i < that.ToAdd.length; i++)
				{
					that.addImages(that.ToAdd[i].page, that.ToAdd[i].images);
				}
				
				if (that.InitalImageId)
					that.setImageById(that.InitalImageId);
				else
					that.switchPage(1);
				
				// Add the events
				that.Elements.NextPage.click(function(){
					that.nextPage();
					return false;		
				});
				
				that.Elements.PrevPage.click(function(){
					that.prevPage();
					return false;		
				});
				
				that.Elements.NextImg.click(function(){
					that.nextImage();
					return false;		
				});
				
				that.Elements.PrevImg.click(function(){
					that.prevImage();
					return false;		
				});
				
				// now select the first image
				if (that.ImagePages.length)
					that.switchImage(that.CurrentPage, that.CurrentImage, false);
			});
		},
		
		/**
		 * Used for back/forward/bookmarks
		 */
		navEvent : function(hash, that)
		{
			var match = hash.match(/^(\d+)/);
			
			if (match)
				this.setImageById(match[1]);
			else if (hash == "" && this.ImagePages.length 
				&& this.ImagePages[0].ImageWrappers.length)
				this.switchImage(1, 1, false);
		},
		
		/**
		 * 
		 */
		setImageById : function(id)
		{
			if (!this.Loaded)
			{
				this.InitalImageId = id;
				return;
			}
			
			var found = null;
			var that = this;
			
			for (var i = 0; i < this.ImagePages.length; i++)
			{
				for (var j = 0; j < this.ImagePages[i].ImageWrappers.length; j++)
				{
					var image = this.ImagePages[i].ImageWrappers[j].Data;
					if (image.id == id)
					{
						found = [i + 1, j + 1];
						break;
					}
				}
				
				if (found)
					break;
			}
			
			if (!found) {
				// ask AJAX for the page
				$.getJSON("ajax/get_page_from_id.cfm", {id : id}, function(json){
					if (json.STATUS == "ok") {
						that.LoadedPages++;
						that.loadPageAjax(json.PAGE + 1, function(){
							that.switchImage(json.PAGE + 1, json.IMAGE, false);
						});
					}
				});
				return;
			}
			
			this.switchImage(found[0], found[1], false);
		},
		
		loadPageAjax : function(page, callback) {
			var that = this;
			$.getJSON("ajax/get_gallery_page.cfm?" + Math.random(), {
				from: this.LoadedPages,
				to: page
			}, function(json){
				var p = 0;
				for (var jsonPage = that.LoadedPages; jsonPage <= page; jsonPage++) {
					var images = json.PAGES[p];
					var prep = [];
					for (var i = 0; i < images.length; i++) {
						prep.push({
							url: images[i].URL.replace("\\'", "'"),
							title: images[i].TITLE,
							name: images[i].NAME,
							desc: images[i].DESC,
							id: images[i].ID
						});
					}
					that.addImages(jsonPage, prep);
					that.LoadedPages = jsonPage;
					p++;
				}
				
				if (callback != null) 
					callback();
			});
		},
		
		/**
		 * Goes to the next page, or stops
		 */
		nextPage : function()
		{
			var that = this;
			if (this.LoadedPages < this.MaxPages) {
				this.loadPageAjax(++this.LoadedPages, function(){
					that.switchPage(that.CurrentPage + 1);
				});
				return true;
			}
			if (this.CurrentPage < this.MaxPages)
			{
				that.switchPage(that.CurrentPage + 1);
				return true;
			}
			return false;
		},
		
		/**
		 * Goes to the prev page, or stops
		 */
		prevPage : function()
		{
			if (this.CurrentPage > 1)
			{
				this.switchPage(this.CurrentPage - 1);
				return true;
			}
			return false;
		},
		
		/**
		 * Goes to the next image, or stops. Also moves to the next page if required
		 */
		nextImage : function()
		{
			if (this.CurrentImage < this.ImagePages[this.CurrentPage - 1].ImageData.length)
			{
				this.switchImage(this.CurrentPage, this.CurrentImage + 1);
			}
			else
			{
				if (this.nextPage())
				{
					this.switchImage(this.CurrentPage, 1);
				}
			}
		},
		
		/**
		 * Goes to the prev image, or stops. Also moves to the next page if required
		 */
		prevImage : function()
		{
			if (this.CurrentImage > 1)
			{
				this.switchImage(this.CurrentPage, this.CurrentImage - 1);
			}
			else
			{
				if (this.prevPage())
				{
					this.switchImage(this.CurrentPage, this.Options.images_per_page);
				}
			}
		},
		
		/**
		 * Switches to a different image in the main image box
		 * @param {Object} page
		 * The page this image is on
		 * @param {Object} image
		 * The image index of this image
		 * @param {bool} doHistory
		 * Should we add this to the history?
		 */
		switchImage : function(page, image, doHistory)
		{
			if (doHistory == null)
				doHistory = true;
			 
			if (!this.ImagePages.length)
				return;
			 
			$(".ImageSelected").each(function(){
				$(this).removeClass("ImageSelected");
			});
			
			if (page != this.CurrentPage)
				this.switchPage(page);
			
			var imageRow = this.ImagePages[page - 1].ImageWrappers[image - 1];
			var imageData = imageRow.Data;
			
			if (doHistory)
			{
				document.title = imageData.name + ", " + imageData.title;
				$.history.load(imageData.id + "-" + imageData.name + ", " + imageData.title);
			}
			
			var ele = $(imageRow.Element);
			ele.addClass("ImageSelected");
			
			this.Elements.MainImage.attr("src", imageData.url);
			this.CurrentImage = image;
			
			this.Elements.CustomerName.html(imageData.name);
			this.Elements.ImageTitle.html(imageData.title);
			this.Elements.ImageDesc.html(imageData.desc);
		},
		
		/**
		 * Switches to a new page
		 * @param {Object} page
		 */
		switchPage : function(page)
		{
			var imageRow = this.ImagePages[page - 1].ImageRow;
			var current = this.ImagePages[this.CurrentPage - 1].ImageRow;
			
			$(imageRow).css("opacity", 0).animate({opacity : 1}, 600);
			
			this.CurrentPage = page;
			this.Elements.ImgSelect.animate({
				left 		: ((350 * (page - 1)) * -1) + "px"
			}, 500);
			
			// now enable all thumbnails
			var imageWrappers = this.ImagePages[this.CurrentPage - 1].ImageWrappers;
			if (!imageWrappers.Loaded) {
				for (var i = 0; i < imageWrappers.length; i++) {
					imageWrappers[i].TheImage.setAttribute("src", imageWrappers[i].Data.url);
				}
				imageWrappers.Loaded = true;
			}
		},
		
		/**
		 * Adds a page of images to the selctor. Can be called from AJAX call or from the page itself
		 * (coldfusion). It will eaither use a set of already created elements, or create new ones if
		 * they don't exist - including the event handelrs for the img tags
		 * @param {Object} page
		 * The page index, starting at 1, of the page these images go in
		 * @param {Object} images
		 * An array of images. They have the following type:
		 * images[0] = {url, name, description}
		 */
		addImages : function(page, images)
		{
			if (!this.Loaded)
			{
				this.ToAdd.push({"page" : page, "images" : images});
				return;
			}
			
			// first, see if the HTML already exists for this set
			var ele = this.Elements.ImgSelect;
			var find = $("#" + this.Options.image_select_bar + " #ImagePage" + page);
			var imagePageEle = null;
			
			if (!find[0])
			{				
				// nopers, we have to create it
				var newImages = 
					$(document.createElement("div"))
						.attr("class", "ImagePage")
						.attr("id", "ImagePage" + page);
						
				// add the rows...
				for (var i = 0; i < images.length; i++)
				{
				}
				
				// and add the PAGE
				ele.append(newImages);
				imagePageEle = newImages;
				
				// we have to add this to our internal structure...
				imageData = {
					ImageData		: images,
					ImageRow		: $("#" + this.Options.image_select_bar + " #ImagePage" + page)[0],			
					ImageWrappers	: []
				};
				
				for (var i = 0; i < images.length; i++)
				{
					var newRow = document.createElement("div");
					newRow.className = "ImageWrapper";
					newRow.setAttribute("id", "ImageP" + page + "I" + (i + 1));
					newRow = $(newRow);
					
					var newImg = document.createElement("img");
					newImg.className = "GalleryImage";
					newImg.setAttribute("width", 68);
					newImg.setAttribute("height", 50);
					newImg.setAttribute("src", this.Options.image_loading);
					var newImageDom = newImg;
					newImg = $(newImg);
							
					newRow.append(newImg);
					newImages.append(newRow);
					
					imageEle = newRow;
					imageEle.Gallery = this;
					
					imageData.ImageWrappers.push({
						Element	: imageEle,
						TheImage : newImageDom
					});
					
					$(newImg).click(function(){
						var jThis = $(this);
						var data = jThis.data("ImageData");
						jThis.data("Gallery").switchImage(
							data.page, data.index);
					});
					
					$(imageEle).hover(function(){
						$(this).addClass("ImageOver");
					}, function(){
						$(this).removeClass("ImageOver");
					});
						
					images[i].page = page;
					images[i].index = i + 1;
					
					newImg.data("ImageData", images[i]);
					newImg.data("Gallery", this);
					
					imageData.ImageWrappers[i].Data = images[i];
					imageData.ImageWrappers[i].Element.ImageData = images[i];
				}
				
				this.ImagePages.push(imageData);
			}
			else
				imagePageEle = find[0];
			
			// now add all of the images
			var imageData = null;

			if (this.ImagePages.length >= (page - 1)) // < damn 1-bassed indexing
			{
			}
			else
				imageData = this.ImagePages[page];
			
			// Now we need to set the width of the inner image select to contain all pages
			this.Elements.ImgSelect.css("width", this.ImagePages.length * 350);
			
		}
		
	});
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	