var DEFAULTTEXTWIDTH, LASTPROJECTPIC = null;
if (isie && engine < 8) DEFAULTTEXTWIDTH = "422px"
else DEFAULTTEXTWIDTH = "322px"

/**
 * This function aids in transitioning text in and out of the info box
 */
function swapText(e, newtext, toStyle, callback) {
	var newWidth = /* (CURRENTPAGE == "general_info") ? "460px" :  */DEFAULTTEXTWIDTH;
	toStyle = Object.extend({
		width: newWidth
	}, toStyle || {});
	/*
	if (isie && engine < 8) {
		toStyle.width = parseInt(toStyle.width) + parseInt(toStyle.paddingLeft) + "px"
	}
	*/
	
	var oldTextHeight = measureTextHeight(e.innerHTML, e.getStyle("width"));
	var newTextHeight = measureTextHeight(newtext, toStyle.width);
	
	new Effect.Morph(e.id, {style: toStyle, duration: 0.5, afterFinish: function() {
		e.update(null);
		insertText(e, newtext);
		if (callback && typeof callback == "function") callback();
	}});
}

/**
 * This function measures text height using a temporary div
 */
function measureTextHeight (text, width) {
	width = width || DEFAULTTEXTWIDTH;
	var tmp = new Element("div", {style: "position: absolute; top: 0px; left: 0px; width: "+width+";"});
	insertText(tmp, text);
	document.body.appendChild(tmp);
	
	var textHeight = tmp.getStyle("height");
	//alert("width: "+tmp.getStyle("width")+" height: "+textHeight);
	tmp.remove();
	return textHeight;
}

/**
 * This function inserts text as a child of the element.
 *
 * @param e (Element) The element to receive the text
 *
 * @param text (String, Array) A string of text or array of
 *		  elements to insert
 */

function insertText(e, text) {
	if (typeof text == "object") {
		text.each(function(name, idx) {
			e.insert({bottom: text[idx]});
		});
	} else if (typeof text == "string")
		e.update(text);
	else alert(new Error("New text format is invalid. Must be an array of elements or a string."));
}

/**
 * This class defines a scrolling thumbnail gallery.
 */

var SlideGallery = Class.create({
	/**
	 * Constructor
	 *
	 * @param section (String) The section name as one of the choices
	 *		  defined in the custom3 values for categories in editor 9
	 *
	 * @param options (Object) Parameter list containing overrides to
	 * 		  standard settings
	 */
	initialize : function(section, options) {
		// set the defaults if they are not defined
		this.options = Object.extend({
			showAtPageLoad : false,
			useSections : false,
			sectionCustomVar: null,
			textarea : "infotext",
			textareawidth : "422px",
			projects : true
		}, options || {});
		
		/**
		 * Class constants
		 */
		this.count = 0;
		this.offset = 0;
		this.padding = 35;
		this.preloadDone = false;
		this.animating = false;
		this.thumbWrapId = "thumbscrollerwrap";
		this.section = null;
		this.container = null;
		this.scroller = null;
		this.images = [];
		this.extraRows = 2;
		this.thumbWidth = 0;
		this.thumbHeight = 0;
		this.galleryWidth = null;
		this.currentIndex = 0;
		this.textarea = null;
		this.projectopen = false;
		if(pagSitename == "interiors"){
			this.ajaxappension = "&interiors=1";
		} else {
			this.ajaxappension = "";
		}
		
		if (!this.options.editor) alert(new Error("Editor number is not defined."));
		
		if (this.options.useSections && (typeof section != "string" || !section)) alert(new Error("Expecting gallery section to be non-empty string, found " + section));
		this.section = section.toLowerCase();
		
		this.textarea = $(this.options.textarea);
		if (!this.textarea) alert(new Error("Element with id \"" + this.options.textarea + "\" does not exist."));
		
		this.createThumbGallery();
	},
	
	/**
	 * Fetches the thumbnail list as well as metadata for the thumbnails
	 * then creates the markup for the gallery, inserting it into the
	 * container with ID defined in variable thumbWrapId of the class constants
	 */
	createThumbGallery : function() {
		var _this = this;
		
		// only do load if intro is not in progress
		if(introInProgress){
			setTimeout(function(){_this.createThumbGallery();}, 250);
		}else{
			var url = "/content/SlideGallery/getThumbList.php?editornum=" + this.options.editor;
			if (this.options.useSections) url += "&section=" + this.section + "&custom=" + this.options.sectionCustomVar + this.ajaxappension;
			
			new Ajax.Request(url, {
				onComplete: function(transport) {
					switch (transport.status) {
						case 406:
							alert(new Error(transport.responseText));
							break;
						default:
							var response = transport.responseJSON;
							_this.thumbWidth = response.width;
							_this.thumbHeight = response.height;
							_this.count = response.count;
							
							if (response.errors && response.errors.length > 0) {
								response.errors.each(function(name, idx) {
									alert(this[idx]);
								}, response.errors);
							}
							
							// create main container for the scroller div
							var container = new Element("div", {
								id: _this.section + "scrollerwrap",
								"class": "scrollerwrap"
							});
							
							$(_this.thumbWrapId).appendChild(container);
							_this.container = container;
							
							// create the scroller div
							_this.galleryWidth = _this.count * _this.thumbWidth;
							var slider = new Element("div", {
								id: _this.section + "scroller",
								"class": "scroller"
							});
							slider.setStyle({
								height: _this.thumbHeight,
								width: _this.galleryWidth * (_this.extraRows * 2 + 1),
								left: _this.calculateLeftPos()
							});
							slider.observe('click', _this.handleCellClick.bind(_this));
							
							container.appendChild(slider);
							container.appendChild(_this.createLink("NEXT", "nextthumb", _this.scrollNext));
							_this.scroller = slider;
							
							var from = _this.extraRows * -1;
							var to = _this.extraRows;
							
							// for each of the gallery clones and gallery itsself, create a TD container and image
							for (var i = from; i <= to; ++i) {
								response.images.each(function(name, idx) {
									var o = this[idx];
									
									var name = o.name;
									if (o.building) name += " | " + o.building;
									// create the table cell to hold the image
									var cell = new Element("div", { name: name });
									cell.setStyle({
										height: _this.thumbHeight,
										width: _this.thumbWidth,
										backgroundImage: "url("+o.faded+")"
									});
									
									if (isie && engine < 8)
										cell.setStyle({ display: "inline" });
									else
										cell.setStyle({ display: "inline-block" });
									
									cell.store("offset", i); // store metadata about the offset
									
									slider.appendChild(cell);
									
									// create the image
									var image;
									if (i == 0) {
										image = new Element("img", {
											height: _this.thumbHeight,
											width: _this.thumbWidth,
											src: o.selected
										});
										image.setOpacity(0);
										
										// store metadata
										image.store("unid", o.unid);
										image.store("name", o.name);
										image.store("building", o.building);
										image.store("text", o.text);
										image.store("projecttext", o.projecttext);
										
										// collect image references into an array
										_this.images.push(image);
										
										if (idx == _this.currentIndex)
											image.setOpacity(100);
									} else { // use a shim
										image = new Element("img", {
											name: "shim",
											src: "/images/shim.gif"
										});
										image.setStyle({
											height: _this.thumbHeight,
											width: _this.thumbWidth
										});
									}
									cell.appendChild(image);
								}, response.images);
							}
							
							this.preloadDone = true;
							
							if (_this.options.showAtPageLoad) {
								OLDGALLERY = CURRENTGALLERY = _this;
								//_this.container.setStyle({ height: _this.thumbHeight });
							}
							break;
					}
				}
			});
		}
	},
	
	createInfoText : function(options) {
		options = Object.extend({
			showNext: true,
			showProjectText: false
		}, options || {});
		
		var image = this.images[this.currentIndex];
		var container = [];
		
		// get the info from the image metadata
		var name = image.retrieve("name");
		var building = image.retrieve("building");
		var text = image.retrieve("text");
		
		var header = new Element("h2");
		header.appendChild(document.createTextNode(name));
		if (building) {
			var sep = new Element("span");
			sep.addClassName("sepbar");
			sep.appendChild(document.createTextNode(" | "));
			
			header.appendChild(sep);
			header.appendChild(document.createTextNode(building));
		}
		
		container.push(header);
		container.push(text);
		
		if (this.options.projects) {
			// create a link to view the project
			var nextLink = this.createLink("VIEW PHOTOS", "graylink", this.openProject)
			if (!options.showNext) nextLink.setStyle({display: "none"});
			container.push(nextLink);
			
			// create a div for the extra project text
			var projecttext = new Element("div", {id: "projecttext"}).update(image.retrieve("projecttext"));
			if (!options.showProjectText) projecttext.setStyle({display: "none"});
			container.push(projecttext);
		}
		
		return container;
	},
	
	createLink : function(text, className, callback, useimg) {
		useimg = useimg || true;
		var container = new Element("div", {"class" : className, style: "cursor: pointer"});
		container.appendChild(document.createTextNode(text));
		if (useimg) container.appendChild(new Element("img", {src: "/images/arrow.gif", width: 7, height: 8, border: 0, style: "margin-left: 10px"}));
		if (callback && typeof callback == "function") container.observe('click', callback.bind(this));
		return container;
	},
	
	scrollNext : function(event) {
		event.stop(); // stop the event from bubbling
		
		if (!this.animating) {
			this.animating = true;
			
			var newIndex = this.currentIndex + 1;
			var offset = newIndex >= this.count ? 1 : 0;
			this.scrollTo(newIndex % this.count, offset);
		}
	},
	
	scrollTo : function(index, offset) {
		this.animating = true;
		var oldImage = this.images[this.currentIndex];
		var oldImageIdx = this.images.indexOf(oldImage);
		
		// set the current index to the new image's index
		this.currentIndex = index;
		
		var _this = this;
		
		// fade out the current image
		new Effect.Opacity(this.textarea, {from: 1.0, to: 0, duration:0.3});
		new Effect.Opacity(oldImage, {from: 1.0, to: 0, duration:0.3, afterFinish: function() {
			var scrollerLeftPos = parseInt(_this.scroller.getStyle("left"));
			
			if (offset != 0)
				_this.scroller.setStyle({ left: scrollerLeftPos + (_this.galleryWidth * offset) });
			
			// Slide the bar over
			new Effect.Morph(_this.scroller, {
				style: 'left: ' + (scrollerLeftPos - _this.getDistance(index, oldImageIdx))+';',
				duration: 0.4,
				transition: Effect.Transitions.sinoidal
			});
			
			var textstyle = {
				width: _this.options.textareawidth,
				paddingLeft: "50px",
				paddingTop: "25px"
			};
			
			// load the new text
			swapText(_this.textarea, _this.createInfoText(), textstyle, function() {
				// fade in the new image and text
				var newImage = _this.images[index];
				new Effect.Opacity(_this.textarea, {from: 0, to: 1.0, duration:0.3});
				new Effect.Opacity(newImage, {from: 0, to: 1.0, duration:0.3, afterFinish: function() { _this.animating = false; }});
			});
		}});
	},
	
	handleCellClick : function(event) {
		event.stop(); // stop the event from bubbling
		if (!this.animating) {
			var e = Event.element(event); // the thing that was clicked on
			// figure out the image/index/offset
			var cells = this.scroller.select("div");
			var div = e.up("div");
			var newImageIdx = cells.indexOf(div) % this.count;
			
			if (newImageIdx != this.currentIndex) { // browsing gallery
				var offset = div.retrieve("offset");
				this.scrollTo(newImageIdx, offset);
			} else if(this.options.projects) { // selecting a project
				this.openProject();
			}
		}
	},
	
	openProject : function() {
		if (!this.animating) {
			this.animating = true;
			this.projectopen = true;
			
			var image = this.images[this.currentIndex];
			var unid = image.retrieve("unid");
			
			var projectLink = this.textarea.down(".graylink");
			var _this = this;
			
			// set our loading cursor
			$('body').setStyle({cursor: 'progress'});
			
			if (projectLink) {
				// create "loading..." div
				var loadDiv = new Element("div", {style : "width: 100%; display: none; height: 14px"}).update("LOADING PROJECT...");
				projectLink.fade({duration: 0.2, afterFinish: function() {
					_this.textarea.insert({bottom: loadDiv});
					loadDiv.appear({ duration: 0.3 });
				}});
				
				var url = "/content/build_project.php?unid=" + unid;
				if (this.options.useSections) url += "&section=" + this.section + "&custom=" + this.options.sectionCustomVar + this.ajaxappension;
				new Ajax.Updater('picnavwrap', url, {evalScripts: true, onComplete: function() {
					$('body').setStyle({ cursor: 'auto' });
					new Effect.Morph('picnavwrap', {style: 'margin-top: 0px', delay: 1.0, duration: 0.5});
					new Effect.Parallel([
						new Effect.Morph("pagetable", {style: "height: " + (parseInt($("pagetable").getStyle("height")) + _this.thumbHeight) + "px", sync: true}),
						new Effect.Morph(_this.container, {style: 'height: 0px', sync: true})
						], {duration:0.5, afterFinish: function() {
							if (image.retrieve("projecttext"))
								Effect.SlideDown("projecttext", {duration: 0.3});	
						}}
					);
					loadDiv.fade({ duration: 0.3, afterFinish: function() { loadDiv.remove(); } });
					
					// create a link to return to the thumbnail gallery
					var returnContainer = new Element("div", {id: "closeproject", style: "padding-top: 8px; padding-right: 8px; float: right; display: none"});
					returnContainer.appendChild(_this.createLink("RETURN TO THUMBNAILS", "thumbreturn", _this.closeProject));
					$("trcol").insert({top: returnContainer});
					returnContainer.appear({duration: 0.5});
					
					_this.animating = false;
				}});
			}
			pageTracker._trackPageview("/portfolio/"+_this.section+"/"+unid);
		}
	},
	
	// for now this will be used to go to the next project, but could feasibly
	// go to any project when given a unid
	gotoProject : function(unid) {
		if (!this.animating) {
			// figure out the index of the next image, then set the current index to that
			var nextIndex = null;
			var imgcount = this.images.length;
			var _this = this;
			
			for (var i = 0; i < imgcount; ++i) {
				if (this.images[i].retrieve("unid") == unid) {
					nextIndex = i;
					break;
				}
			}
			
			if (nextIndex === null) alert(new Error("Next project index not found!"));
			else {
				this.animating = true;
				LASTPROJECTPIC = null;
				// set our loading cursor
				$('body').setStyle({cursor: "progress"});
				
				// hide the old thumbnail image
				var oldImage = this.images[this.currentIndex];
				oldImage.setOpacity(0);
				
				this.currentIndex = nextIndex;
				var newImage = this.images[this.currentIndex];
				
				// even though the thumbnails are hidden, scroll to the new index and show the new image
				newImage.setOpacity(1);
				this.scroller.setStyle({ left: this.calculateLeftPos() });
				
				var loadDiv = new Element("div", {style : "width: 100%; display: none; height: 14px"}).update("LOADING PROJECT...");
				this.textarea.insert({bottom: loadDiv});
				loadDiv.appear({ duration: 0.3 });
				
				new Effect.Morph('picnavwrap', {style: 'margin-top: -20px', duration:0.5});
				new Effect.Fade('mainpic', {duration:0.5, afterFinish: function() {
					var url = "/content/build_project.php?unid=" + unid;
					if (_this.options.useSections) url += "&section=" + _this.section + "&custom=" + _this.options.sectionCustomVar + this.ajaxappension;
					new Ajax.Updater('picnavwrap', url, {evalScripts: true, onComplete: function() {
						new Effect.Morph('picnavwrap', {style: 'margin-top: 0px', delay: 1.0, duration: 0.5});
						
						new Effect.Opacity(_this.textarea.id, {from: 1.0, to: 0, duration:0.4, afterFinish: function() {
							var textstyle = {
								width: _this.options.textareawidth
							};
							
							swapText(_this.textarea, _this.createInfoText({showNext: false, showProjectText: true}), textstyle, function() {
								new Effect.Opacity(_this.textarea.id, {from: 0, to: 1.0, duration:0.3});
								_this.animating = false;
								$('body').setStyle({cursor: "auto"});
							});
						}});
					}});
				}});
			}
			pageTracker._trackPageview("/portfolio/"+_this.section+"/"+unid);
		}
	},
	
	closeProject : function(callback, openGallery) {
		if (!this.animating) {
			this.animating = true;
			LASTPROJECTPIC = null;
			openGallery = openGallery === undefined ? true : openGallery;
			var _this = this;
			var dimensions = $('body').getDimensions();
			var leftwidth = Math.round(.45 * dimensions.width);
			var image = this.images[this.currentIndex];
			
			var wrapper = function() {
				_this.projectopen = false;
				_this.animating = false;
				
				// restore project link
				var projectLink = _this.textarea.down(".graylink");
				if (projectLink) projectLink.appear({duration: 0.2});
				
				if (callback && typeof callback == "function") callback();
			}
			
			new Effect.Fade('mainpic', {duration:0.5, afterFinish: function() {
				var projecttext = $("projecttext");
				if (projecttext && image.retrieve("projecttext")) projecttext.slideUp({duration:0.5});
				
				new Effect.Morph('mainpicwrap',{ style:'width: ' + (leftwidth-1) + 'px; height: 1px; background-color: #eee', duration:0.5});
				new Effect.Morph('picnavwrap', {style: 'margin-top: -20px', duration:0.5});
				new Effect.Morph(INFOTEXT, {style: "padding-top: 25px; padding-left: 50px; width: "+DEFAULTTEXTWIDTH, duration: 0.5, afterFinish: function() {
					$("closeproject").fade({ duration: 0.3, afterFinish: function() { $("closeproject").remove(); } });
					if (openGallery) {
						new Effect.Parallel([
							new Effect.Morph("pagetable", {style: "height: " + (parseInt($("pagetable").getStyle("height")) - _this.thumbHeight) + "px", sync: true}),
							new Effect.Morph(_this.container, {style: "height: " + _this.thumbHeight + "px", sync: true})
							], {duration: 0.5, afterFinish : function() {
								wrapper();
							}}
						);
					} else {
						wrapper();
					}
				}});
			}});
			pageTracker._trackPageview("/portfolio/"+_this.section+"/");
		}
	},
	
	show : function() {
		var _this = this;
		
		var wrapper = function() {
			var textstyle = {
				width: _this.options.textareawidth,
				paddingLeft: "50px",
				paddingTop: "25px"
			};
			
			// load the new text
			swapText(_this.textarea, _this.createInfoText(), textstyle, function() {
				new Effect.Opacity(_this.textarea.id, {from: 0, to: 1.0, duration:0.3});
			});
			
			new Effect.Parallel([
				new Effect.Morph("pagetable", {style: "height: " + (parseInt($("pagetable").getStyle("height")) - _this.thumbHeight) + "px", sync: true}),
				new Effect.Morph(_this.container, {style: "height: " + _this.thumbHeight + "px", sync: true})
				], {duration: 0.5}
			);
		}
		
		// reset the left position in case widths changed
		this.scroller.setStyle({ left: this.calculateLeftPos() });
		var opacity = this.textarea.getOpacity();
		
		if (opacity == 0) wrapper();
		else new Effect.Opacity(this.textarea.id, {from: 1.0, to: 0, duration:0.4, afterFinish: wrapper});
	},
	
	hide : function(callback) {
		new Effect.Opacity(this.textarea.id, {from: 1.0, to: 0, duration:0.4});
		if (this.projectopen) this.closeProject(callback, false);
		else {
			new Effect.Parallel([
				new Effect.Morph("pagetable", {style: "height: " + (parseInt($("pagetable").getStyle("height")) + this.thumbHeight) + "px", sync: true}),
				new Effect.Morph(this.container, {style: 'height: 0px', sync: true})
				], {duration:0.5, afterFinish: function() {
					if (callback && typeof callback == "function") callback();
				}}
			);
		}
	},
	
	getDistance : function(newID, oldID) {
		oldID = oldID | 0;
		return (newID - oldID) * this.thumbWidth;
	},
	
	calculateLeftPos : function() {
		var dimensions = $('body').getDimensions();
		var leftWidth = Math.round(.45 * dimensions.width);
		return leftWidth + this.padding - (this.galleryWidth * this.extraRows) - (this.currentIndex * this.thumbWidth);
	},
	
	isDoneLoading : function() {
		return this.preloadDone;
	}
});
