
(function($) {

	function getHashFromString(hash) {
		if (!hash) return -1;
		hash = hash.replace(/^.*#/, '');
		if (isNaN(hash)) return -1;
		return (+hash);
	}

	function getIndex(gallery, hash) {
		return hash-gallery.offset;
	}

	function clickHandler(e, gallery, link) {
	//	gallery.pause();
	//	if (!gallery.settings.enableHistory) {
			var hash = getHashFromString(link.href);
			if (hash >= 0) {
				var index = getIndex(gallery, hash);
				if (index >= 0 && index != gallery.currentIndex)
					gallery.goto(index);
			}
			e.preventDefault();
	//	}
	}


	$.fn.glr = function(){
		$.extend(this, {
			initialize : function(){
				this.data = [];
				var gallery = this;
				gallery.offset = 0;

				this.$thumbsContainer.find('div.thumb').each(function(i) {
					var $div = $(this);
					var $aThumb = $div.find('a');
					var $iThumb = $aThumb.find('img');

					var hash = gallery.offset + i;

					gallery.data.push({
						slideUrl : $div.attr('slideurl') || $aThumb.attr('href'),
						title : $iThumb && $iThumb.attr('title') || '',
						hash : hash
					});

					if($div.attr('current')){
						gallery.currentIndex = i;
					}

					$aThumb.attr('href','#' + hash);
					$aThumb.click(function(e){
						clickHandler(e, gallery, this);
					});
				});

				if(this.data.length < 1){
					gallery.data.push({
						slideUrl : this.$imageContainer.attr('slideurl'),
						title : this.$imageContainer.find('img').attr('title') || '',
						hash : 0
					});
				}
			},

			isPreloadComplete: false,

			preloadInit: function() {
				if (this.settings.preloadAhead == 0) return this;
				
				this.preloadStartIndex = this.currentIndex;
				var nextIndex = this.getNextIndex(this.preloadStartIndex);
				return this.preloadRecursive(this.preloadStartIndex, nextIndex);
			},


			preloadRelocate: function(index) {
				this.preloadStartIndex = index;
				return this;
			},

			preloadRecursive: function(startIndex, currentIndex) {
				// Check if startIndex has been relocated
				if (startIndex != this.preloadStartIndex) {
					var nextIndex = this.getNextIndex(this.preloadStartIndex);
					return this.preloadRecursive(this.preloadStartIndex, nextIndex);
				}

				var gallery = this;

				var imageData = this.data[currentIndex];
				if (!imageData)
					return this;

				// If already loaded, continue
				if (imageData.image)
					return this.preloadNext(startIndex, currentIndex); 
				
				// Preload the image
				var image = new Image();
				
				image.onload = function() {
					imageData.image = this;
					gallery.preloadNext(startIndex, currentIndex);
				};

				image.alt = imageData.title;
				image.src = imageData.slideUrl;

				return this;
			},

			preloadNext: function(startIndex, currentIndex) {
				var nextIndex = this.getNextIndex(currentIndex);
				if (nextIndex == startIndex) {
					this.isPreloadComplete = true;
				} else {
					var gallery = this;
					setTimeout(function() { gallery.preloadRecursive(startIndex, nextIndex); }, 100);
				}
				return this;
			},

			getNextIndex: function(index) {
				var nextIndex = index+1;
				if (nextIndex >= this.data.length)
					nextIndex = 0;
				return nextIndex;
			},

			goto: function(index) {
				if (index < 0) index = 0;
				else if (index >= this.data.length) index = this.data.length-1;
				this.currentIndex = index;
				this.preloadRelocate(index);
				return this.refresh();
			},


			refresh: function() {
				var imageData = this.data[this.currentIndex];
				if (!imageData)
					return this;
				
				var isTransitioning = true;
			//	var isTransitioning = false;

				var gallery = this;

				var transitionOutCallback = function() {
					// Flag that the transition has completed
					isTransitioning = false;

					// Update Controls
					if (gallery.$controlsContainer) {
						gallery.$controlsContainer
							.find('div.nav-controls a.prev').attr('href', '#'+gallery.data[gallery.getPrevIndex(gallery.currentIndex)].hash).end()
							.find('div.nav-controls a.next').attr('href', '#'+gallery.data[gallery.getNextIndex(gallery.currentIndex)].hash);
					}

					var imageData = gallery.data[gallery.currentIndex];

					// Replace Caption
					if (gallery.$captionContainer) {
						gallery.$captionContainer.empty().append(imageData.caption);
					}

					if (imageData.image) {
						gallery.buildImage(imageData.image);
					} else {
						// Show loading container
						if (gallery.$loadingContainer) {
						//	var $thumbs = gallery.$thumbsContainer.find('ul.thumbs').children();
						//	gallery.$loadingContainer.find('img').attr('src', $thumbs.eq(gallery.currentIndex).find('img').attr('src'));
							gallery.$loadingContainer.show();
						}
					}
				}

				if (this.settings.onTransitionOut) {
					this.settings.onTransitionOut(transitionOutCallback);
				} else {
				//	this.$transitionContainers.hide();
				//	this.$transitionContainers.fadeTo('fast', 0.5, transitionOutCallback);
					transitionOutCallback();
				}

				if (!imageData.image) {
					var image = new Image();

					image.onload = function() {
						imageData.image = this;
						if (!isTransitioning) {
							gallery.buildImage(imageData.image);
						}
					};
					image.alt = imageData.title;
					image.src = imageData.slideUrl;
				}

				this.relocatePreload = true;
			//	return this.syncThumbs();
			},


			buildImage: function(image) {
				var gallery = this;

				var transitionOutCallback = function() {
					gallery.$imageContainer.empty();

					var nextIndex = gallery.getNextIndex(gallery.currentIndex);

					// Hide the loading conatiner
					if (gallery.$loadingContainer) {
						gallery.$loadingContainer.hide();
					}

					// Setup image
					gallery.$imageContainer
						.append('<span class="image-wrapper"><a class="advance-link" rel="history" href="#'+gallery.data[nextIndex].hash+'" title="'+image.alt+'"></a></span>')
						.find('a')
						.append(image)
						.click(function(e) {
							clickHandler(e, gallery, this);
						});

					gallery.$transitionContainers.fadeTo('fast', 1.0);
				}

				this.$transitionContainers.fadeTo('fast', 0.0, transitionOutCallback);
				return this;
			}
		});


		this.$imageContainer = this.find('#slide');
		this.$thumbsContainer = this.find('#thumbs');
		this.$loadingContainer = this.find('#loading');

		this.$transitionContainers = $([]);
		if (this.$imageContainer)
			this.$transitionContainers = this.$transitionContainers.add(this.$imageContainer);
		if (this.$captionContainer)
			this.$transitionContainers = this.$transitionContainers.add(this.$captionContainer);

		this.settings = {};
		this.$loadingContainer.hide();

		this.initialize();

	//	this.currentIndex = 0;
		var gallery = this;


		this.goto(this.currentIndex || 0);

		setTimeout(function() { gallery.preloadInit(); }, 1000);

	}
})(jQuery);
