/**
 * JS Image Gallery
 **/

	if (typeof PLY != 'object') PLY = {};
	if (!PLY.UI) PLY.UI = {};
	if (!PLY.Settings) PLY.Settings = {};
	if (!PLY.Utilities) PLY.Utilities = {};
	
	/**
	 * Site Related Display Settings
	 **/

	/**
	 * Controls the speed of Gallery Fades. 
	 * Can be normal, fast, slow or a millisecond integer value 
	 **/
	PLY.Settings.GalleryFadeSpeed 				= 'normal';
		
	/**
	 * Controls the interval on which the Gallery gets
	 * auto-rotated.
	 **/
	PLY.Settings.GalleryAutoRotationInterval 				= 8000;

	/**
	 * PLY Utilities Namespace
	 **/
	/**
	 * PLY ImageLoader
	 **/
	PLY.Utilities.ImageLoader = {
		Images : [],
		LoadImageSet : function(arrImagePaths, callback) {
			if(typeof arrImagePaths == 'string') arrImagePaths = [ arrImagePaths ];
			var _imageCount = arrImagePaths.length;
			var _loadedImageCount = 0;
			$.each(arrImagePaths, function(index, strImagePath) {
				if(PLY.Utilities.ImageLoader.GetImage(strImagePath) == null) {
					var objImage = new PLY.Utilities.Image(strImagePath);
					PLY.Utilities.ImageLoader.Images.push(objImage);
					objImage.$image.load(function() {
						_loadedImageCount++;
						if(_loadedImageCount == _imageCount && typeof callback == 'function')
							callback();
					});
				} else {
					_imageCount--;
					if(_imageCount == 0 && typeof callback == 'function') callback();
				}
			});
		},
		IsImageLoaded : function(strImagePath) {
			if(typeof strImagePath != 'string') return false;
			$image = PLY.Utilities.ImageLoader.GetImage(strImagePath);
			if($image != null) {
				return PLY.Utilities.ImageLoader.GetImage(strImagePath).isLoaded;
			} else {
				return false;
			}
		},
		GetImage : function(strImagePath) {
			var _image = null;
			$(PLY.Utilities.ImageLoader.Images).each(function(index, objImage) {
				if(objImage.strPath == strImagePath) _image = objImage;
			});
			return _image;
		}
	};

	/**
	 * Image Class
	 **/
	PLY.Utilities.Image = function(strPath) {
		var _this = this;
		this.strPath = (strPath ? strPath : '');
		this.isLoaded = false;
		this.$image = $('<img>').attr('src', _this.strPath);
		this.$image.load(function() {
			_this.isLoaded = true;
		});
	};

	/**
	 * Helper function to get the height of the "More Info"
	 * containers, which are absolutely positioned.
	 *
	 * @param {jQuery} The jQuery Extended Element.
	 *
	 * @param {Integer} The height of the element.
	 **/
	PLY.Utilities.GetPhotoBoxAbsoluteElementHeight = function($element) {
		$eleParent	= $element.parent();
		$element 	= $element.clone();
		$($eleParent).append($('<div>').attr('id', 'hiddenSizeBox').css({ 'height' : '0px', 'visibility' : 'hidden', 'width' :  $eleParent.outerWidth(), 'overflow' : 'hidden' }));
		$eleSizeBox = $('#hiddenSizeBox');
		$($eleSizeBox).append($element.css({ 'position' : 'relative', 'height' : 'auto' }));
		$intEleHeight = $element.outerHeight();
		$eleSizeBox.remove();
		return $intEleHeight;
	};

	/**
	 * PLY UI Namespace
	 **/

	/**
	 *
	 **/
	PLY.UI.Gallery = function(hshCustomOptions) {
		
		// Reference for Object Instance within callback function() {} scope.
		var _this = this;
		
		//default values for configuration options.
		var hshOptions = {
			'imageContainerCssSelector' : ''
			,'titleContainerCssSelector' : ''
			,'descContainerCssSelector' : ''
			,'buttonCssSelector' : ''
			,'nextButtonCssSelector' : ''
			,'prevButtonCssSelector' : ''
			,'dataCssSelector' : ''
			,'autoRotationInterval' : 8000
			,'fadeSpeed'	: 'normal'
			,'loadingImagePath' : ''
			,'toggleInfoBox' : false
		}

		//merge passed in option params to override the defaults
		for (key in hshOptions)
		{
			if (hshCustomOptions[key] != null)
			{
				hshOptions[key] = hshCustomOptions[key];
			}
		}
		
		/* Class Variables */
		this.$imageContainer 	 	= $(hshOptions.imageContainerCssSelector);	
		this.$titleContainer		= $(hshOptions.titleContainerCssSelector);
		this.$descContainer			= $(hshOptions.descContainerCssSelector);
		this.$arrButtons		 	= $(hshOptions.buttonCssSelector);
		this.$nextButton		 	= $(hshOptions.nextButtonCssSelector);
		this.$prevButton		 	= $(hshOptions.prevButtonCssSelector);

		this.arrData				= [];
		this.fadeSpeed				= hshOptions.fadeSpeed;
		this.autoRotationInterval	= hshOptions.autoRotationInterval;
		this.strLoadingImagePath   	= hshOptions.loadingImagePath;
		this.bToggleInfoBox			= hshOptions.toggleInfoBox;
		this.intLoadingImageHeight 	= 32;
		this.intLoadingImageWidth  	= 32;
		this.intActiveItemIndex		= 0;
		this.isPaused				= false;
		
		// Get the Data for the Gallery, from a hidden container
		var arrImagePathsToLoad = [ this.strLoadingImagePath ];
		jQuery.each($(hshOptions.dataCssSelector), function(i, ele) {
			var strImagePath = $(ele).find('.imagePath').text();
			_this.arrData.push({
				'title' : $(ele).find('.imageTitle').html(),
				'desc'	: $(ele).find('.imageDesc').html(),
				'url'	: $(ele).find('.imageUrl').html(),
				'path'	: strImagePath
			});
			arrImagePathsToLoad.push(strImagePath);
		});
		
		// Start preloading the images related to the gallery
		PLY.Utilities.ImageLoader.LoadImageSet(arrImagePathsToLoad);
		
		// Setup Click Events for the numbered (1, 2, 3) buttons
		// which switch out the photo, title, and description on click.
		jQuery.each(this.$arrButtons, function(index, eleButton) {
			$(eleButton).click(function() {
				// Do nothing if you're already active
				if($(this).hasClass('active')) { return false; }
				_this.DisplayGalleryItem(index);
				// Reset the rotation interval
				_this.startRotationInterval();
				return false;
			});
		});

		//Setup click Events for the Next/Prev buttons
		this.$nextButton.click(function() {
			_this.DisplayNextGalleryItem();
			_this.isPaused = true;
			return false;
		});

		this.$prevButton.click(function() {
			_this.DisplayPrevGalleryItem();
			_this.isPaused = true;
			return false;
		});

		if (this.bToggleInfoBox)
		{
			// "More Info" button click.
			$('#moreInfo').click(function() {
				$aboutBox = $('#aboutBox');
				$button	  = $(this);
				if(parseInt($aboutBox.css('height'), 10) == 0) {
					eleHeight = PLY.Utilities.GetPhotoBoxAbsoluteElementHeight($aboutBox);
					_this.isPaused = true;
					$aboutBox.animate({'height' : eleHeight }, function() {
						$button.find('.button').text('-');
						$button.find('a').text('Hide');	
					});
				} else {
					$aboutBox.animate({'height' : '0px'}, function() {
						$button.find('.button').text('+');
						$button.find('a').text('More Info');
						_this.isPaused = false;
					});
				}
			});
		}
	}

	/**
	 * Display the Next Gallery Item in the sequence.  Starts over
	 * upon reaching the end of the gallery item collection.
	 *
	 * @return {void}
	 **/
	PLY.UI.Gallery.prototype.DisplayNextGalleryItem = function() 
	{
		var intNextItemIndex = (this.intActiveItemIndex >= this.arrData.length - 1) ? 0 : this.intActiveItemIndex + 1;
		this.DisplayGalleryItem(intNextItemIndex);

	};

	/**
	 * Display the Previous Gallery Item in the sequence.  Starts over
	 * upon reaching the beginning of the gallery item collection.
	 *
	 * @return {void}
	 **/
	PLY.UI.Gallery.prototype.DisplayPrevGalleryItem = function() 
	{	
		var intPrevItemIndex = (this.intActiveItemIndex <= 0) ? this.arrData.length - 1 : this.intActiveItemIndex - 1;
		this.DisplayGalleryItem(intPrevItemIndex);
	};

	/**
	 * Display the Gallery Item at the specified index, if it exists.
	 * 
	 * @param {Integer} intIndex Required The index of the item to display.
	 *
	 * @return {void}
	 **/
	PLY.UI.Gallery.prototype.DisplayGalleryItem = function(intIndex) {
		if(typeof this.arrData[intIndex] != 'undefined' && intIndex != this.intActiveImageIndex) {
			
			// Current Image
			var $curImage 			= this.$imageContainer.children().first();
			// Next Image
			var strNextImagePath 	= this.arrData[intIndex].path;
			var strNextImageTitle 	= this.arrData[intIndex].title;
			var strNextImageDesc 	= this.arrData[intIndex].desc;
			var strNextImageUrl		= this.arrData[intIndex].url;
			// Start the process of hiding the current one and showing the next
			
			var _this = this;
			$curImage.fadeOut(this.fadeSpeed, function() {
				$curImage.remove();
				// Check if we've already loaded the next image, if not show the loading
				// graphic and load it, once its done loading show it.
				if(!PLY.Utilities.ImageLoader.IsImageLoaded(strNextImagePath)) {
					$loadingImage = PLY.Utilities.ImageLoader.GetImage(_this.strLoadingImagePath).$image;
					strLeftMargin = ( parseInt(_this.$imageContainer.width(), 10) - _this.intLoadingImageWidth ) / 2;
					strTopMargin  = ( parseInt(_this.$imageContainer.height(), 10) - _this.intLoadingImageHeight ) / 2;
					$loadingImage.css({
						'margin-left' : strLeftMargin + 'px',
						'margin-top'  : strTopMargin + 'px'
					});
					_this.$imageContainer.append($loadingImage);
					PLY.Utilities.ImageLoader.LoadImageSet([ strNextImagePath ], function() {
						$loadingImage.remove();
						$nextImage = PLY.Utilities.ImageLoader.GetImage(strNextImagePath).$image;
						_this.renderNewItem($nextImage, strNextImageTitle, strNextImageDesc, strNextImageUrl);
					});
				} else {
					$nextImage = PLY.Utilities.ImageLoader.GetImage(strNextImagePath).$image;
					_this.renderNewItem($nextImage, strNextImageTitle, strNextImageDesc, strNextImageUrl);						
				}					
				// Set the active button
				_this.SetActiveButton(intIndex);
				_this.intActiveItemIndex = intIndex;	
			});
		}
	};

	PLY.UI.Gallery.prototype.SetActiveButton = function(intIndex) {
		if(this.$arrButtons != null && typeof this.$arrButtons[intIndex] != 'undefined') {
			this.$arrButtons.filter('.active').removeClass('active');
			$(this.$arrButtons[intIndex]).addClass('active');
		}
	};

	/**
	 * Handles updating the image, description, and title.
	 **/
	PLY.UI.Gallery.prototype.renderNewItem = function($objImage, strTitle, strDescription, strUrl) {
		if (this.bToggleInfoBox)
		{
			this.hideAboutBox();
		}
		$objImage.hide();

		$objImage.attr('title',strTitle);

		//if the url has a value, wrap the image in an a tag
		if (strUrl != '')
		{
			var $objElement = $('<a>').attr('href', strUrl);
			$objElement.append($objImage.attr('border',0));
		}
		else
		{
			var $objElement = $objImage;
		}

		this.$imageContainer.append($objElement);

		$objImage.fadeIn(this.fadeSpeed);

		this.$titleContainer.html(strTitle);
		this.$descContainer.html(strDescription);
	};
	
	/**
	 * Handles automatic image rotation.
	 **/
	PLY.UI.Gallery.prototype.startRotationInterval = function() {
		if(this.interval)
		{
			clearInterval(this.interval);
		}
		var _this = this;
		this.interval = setInterval(
			function() {
				if(!_this.isPaused)
					_this.DisplayNextGalleryItem();
			},
			this.autoRotationInterval
		);
	};
	
	/**
	 * Hides the About Box.
	 **/
	PLY.UI.Gallery.prototype.hideAboutBox = function() {
		var _this = this;
		$('#aboutBox').animate({'height' : '0px'}, function() {
			$('#moreInfo').find('.button').text('+');
			$('#moreInfo').find('a').text('More Info');
			_this.isPaused = false;
		});
	};
