(function($) {
	
	$.fn.initSlideshowTabs = function ($slideshow) {
	
		var tabInit = false;
		var tabCurrent;
		var tabNew;
		var $tabNav = $("ul#slideshowTabs");
		var $tabNavItem = $tabNav.find("li");
		var tabNavItemHeight = $tabNavItem.eq(0).height();
		var $tabNavLink = $tabNavItem.find("a");
		var $slideshowGroup = $slideshow;
		
		$tabNavItem.each(function() {
			$item = $(this).find('.tabContent');
			var height = $item.height();
			var top = (tabNavItemHeight-height)/2+3;
			$item.css("top",top);
		});
		
		$tabNavItem.mouseover(function() {
			var $tab = $(this);
			if (!$tab.hasClass("current")){
				$tab.addClass("over");
				$tab.stop().animate({marginLeft:0}, 300);
			}
			Cufon.replace('#slideshowTabs h4',{hover: true,fontFamily: 'VAG Rounded'});
		});
		
		
		$tabNavItem.mouseout(function() {
			var $tab = $(this);
			$tab.removeClass("over");
			if (!$tab.hasClass("current")){
				$tab.stop().animate({marginLeft:10}, 300);
			}
			Cufon.replace('#slideshowTabs h4',{hover: true,fontFamily: 'VAG Rounded'});
		});
		
		// Users can click a tab, this will stop the auto selection of the next tab in sequence
		$tabNavItem.click(function() {
			tabClicked($tabNavItem.index(this), true)
		});
		
		// Create and use dummy tab nav, this allows auto selection of next tab in sequence
		$tabNav.parent().append('<ul id="slideshowTabsDummy"></ul>');
		var $tabNavDummy = $('ul#slideshowTabsDummy');
		for(x=0;x<$tabNavItem.size();x++) {
			$tabNavDummy.append('<li></li>');
		}
		var $tabNavDummyItem = $tabNavDummy.find("li");
		
		$tabNavDummyItem.click(function() {
			tabClicked($tabNavDummyItem.index(this), false);
		});
		
		// Trigger first slideshow
		$tabNavDummyItem.eq(0).click();
		
		function tabClicked(index,userClick) {
			
			// Use data store for tab element as used in plugin
			if(userClick){
				$tabNav.data("tabUserSelected",true);
			} else {
				$tabNav.data("tabUserSelected",false);	
			}
			
			tabNew = index;
			// Uncomment this if you'd like to allow user to retrigger the current tab
			//if (tabNew != tabCurrent) {
				$tabNavItem.eq(tabCurrent).removeClass("current").animate({marginLeft:10}, 300);
				$tabNavItem.eq(tabNew).addClass("current").animate({marginLeft:0}, 300);
				if (tabCurrent != null) {
					if (tabNew != tabCurrent) {
						// Hide the currently active slideshow if we're not restarting the current one
						$slideshowGroup.eq(tabCurrent).fadeOut(1500);
					}
					// Reset the currently active slideshow
					$slideshow.resetSlideshow(tabCurrent);
				}
				// Display the active slideshow
				$slideshowGroup.eq(tabNew).fadeIn(1000);
				tabCurrent = tabNew;
				// Trigger play on this slideshow, use new tab index to trigger correct instance of slideshow
				$slideshow.playSlideshow(tabNew);

			//}
			
		}
		
		$tabNavLink.click(function() {
			window.location = $(this).attr("href");
		});
		
		$tabNavLink.mouseover(function() {
			$(this).css("text-decoration","underline");
		});
		
		$tabNavLink.mouseout(function() {
			$(this).css("text-decoration","none");
		});
	
	}
	
	// Functions used by tab navigation
	$.fn.resetSlideshow = function(slideshowInstance) {
		slideshow[slideshowInstance].resetSlideshow();
	}
	
	$.fn.playSlideshow = function(slideshowInstance) {
		slideshow[slideshowInstance].playSlideshow();
	}
	
	// Allow for multiple instances of slideshow and ability to target each instance by slideshowInstance[i]
	var slideshow = [];
	var slideshowInstance = 0;
	var multipleSlideshows = false;

	$.fn.initSlideshow = function(params) {
		
		var TEXT_EVENT = "update_the_text";
		
		// Slideshow class
		function Slideshow($object, options, instance) {
			
			// Console.log("instance: "+instance);
			
			// Options
			var autoPlay			= options.autoPlay;
			var mouseoverPause		= options.mouseoverPause;
			var displayPlayButton 	= (mouseoverPause) ? false : true; // Show play button if there is no pause on mouseover
			var displayTime			= returnPosNumber(options.displayTime);
			var transitionSpeed		= returnPosNumber(options.transitionSpeed);
			var captionSpeed		= returnPosNumber(options.captionSpeed);	
			var timerDisplay		= options.timerDisplay;
			var timerOpacity		= options.timerOpacity;
			var singleSlideshow		= options.singleSlideshow;
			
			// Initialise variables
			var currentSlideIndex	= 0;
			var numSlides;
			var $tabNav 			= $("ul#slideshowTabs");
			var numTabs 			= $("ul#slideshowTabs li").size();
			var timerId 			= null;
			var ie 					= (jQuery.browser.ie) ? true : false;
			var $currentSlideshow 	= $(".slideshowGroup", $object);
			var slideshowWidth		= parseInt($currentSlideshow.css("width"));
			var slideshowHeight		= parseInt($currentSlideshow.css("height"));
			var $imageLink 			= $currentSlideshow.find(">a:first");				
			var $textBox 			= $currentSlideshow.find("div.slideshowText");
			var $preloader 			= $currentSlideshow.find("div.slideshowPreloader");			
			var $slideshowNav 		= $currentSlideshow.find("div.slideshowNav");
			var $slideshowNavNum 	= $currentSlideshow.find("div.slideshowSlides");
			var $slideshowList 		= $slideshowNavNum.find("ul>li");
			var $extraButtons		= $currentSlideshow.find("div.slideshowExtraButtons");	
			var $playBtn 			= $extraButtons.find("div.slideshowPlay");
			var $timer;
			var $items;
			var $innerText;
			
			// Assign passed in slideshowInstance reference
			var slideshowInstance = instance;
			multipleSlideshows = (slideshowInstance > 0) ? true : false;
			
			// Init slideshow
			this.init = function(ref) {
				numSlides = $slideshowList.size();
				$items = new Array(numSlides);
				
				// Init components
				$preloader.css({width:slideshowWidth,height:slideshowHeight}).show();
				initTextBox();
				initItems();
				initExtraButtons();
				initSlideshowNav();
				initTimerBar();
				
				// Init image loading
				loadImg(0);
				
				// Display initial image
				loadSlideContent(currentSlideIndex);
				
				// if this is a single slideshow we need to fade it in, otherwise the clicked tab will do this
				if (singleSlideshow) {
					$object.fadeIn(1000)
				}
			}
			
			// Init text box
			var initTextBox = function() {								
				$textBox.append("<div class='slideshowTextInner'></div>");
				$innerText = $textBox.find("div.slideshowTextInner");	
				$currentSlideshow.bind(TEXT_EVENT, updateText);
			}
			
			// Init slideshow nav
			var initSlideshowNav = function() {	
				$slideshowNav.css("visibility", "visible");
			}
			
			// Init extra buttons
			var initExtraButtons = function() {
				
				// Config play button
				if (displayPlayButton) {
					if (autoPlay) {
						$playBtn.addClass("pause");
					}			
					$playBtn.click(togglePlay).mouseover(buttonOver).mouseout(buttonOut).mousedown(preventDefault);
				}
				else {
					$playBtn.hide();
				}
				
				if (mouseoverPause) {
					$currentSlideshow.hover(pauseSlideshow, playSlideshow);
				}
			}			
			
			// Init timer bar
			var initTimerBar = function() {
				$currentSlideshow.append("<div class='slideshowTimer'></div>");
				$timer = $currentSlideshow.find(".slideshowTimer").data("pct", 1);
				if (timerDisplay) {
					$timer.css({opacity:timerOpacity, visibility:"visible"});
				}
				else {
					$timer.hide();
				}
			}
			
			// Init items
			var initItems = function() {
				$slideshowList.each(
					function(n) {
						var $imgLink = $(this).find(">a:first");
						$(this).data({imgurl:$imgLink.attr("href"), caption:$imgLink.attr("title")});
						initSlideCaption($(this));				
						$items[n] = $(this);
						$(this).append(n+1);
					}
				);
				$innerText.css({width:"auto", height:"auto"}).html("");
				$textBox.css("visibility", "visible");
				$slideshowList.click(slideshowNavClick).mouseover(slideshowNavOver).mouseout(slideshowNavOut).mousedown(preventDefault);
			}			
			
			// Init slide caption
			var initSlideCaption = function($item) {				
				var $caption = $item.find(">div:first");				
				$innerText.html($caption.html());
			}
			
			// On slideshow nav (numbered nav) click
			var slideshowNavClick = function() {
				resetTimer();
				currentSlideIndex = $(this).index();
				loadSlideContent(currentSlideIndex);
				return false;
			}
			
			// On slideshow nav (numbered nav) mouseover
			var slideshowNavOver = function() {
				$(this).addClass("over");
			}
			
			// On slideshow nav (numbered nav) mouseout
			var slideshowNavOut = function() {
				$(this).removeClass("over");
			}
			
			// Go to previous slide
			var previousSlide = function() {
				resetTimer();
				currentSlideIndex = (currentSlideIndex > 0) ? (currentSlideIndex - 1) : (numSlides - 1);
				loadSlideContent(currentSlideIndex);	
				return false;
			}
			
			// Go to next slide
			var nextSlide = function() {
				// CurrIndex = (currentSlideIndex < numSlides - 1) ? (currentSlideIndex + 1) : 0;
				// If this isn't the last image in the group show the next image
				if (currentSlideIndex < numSlides - 1) {
					currentSlideIndex ++;
					loadSlideContent(currentSlideIndex);
				// Last image in this group, trigger next slideshow group unless user has selected a tab or there is only one slidshow
				} else if ($("ul#slideshowTabs").data("tabUserSelected") == false && multipleSlideshows) {
					// Reset index for next time
					currentSlideIndex = 0;
					//("last image in group "+slideshowInstance+" numTabs: "+numTabs);
					var nextTabIndex = slideshowInstance+1;
					if(nextTabIndex == numTabs){
						nextTabIndex = 0;
					}
					$("ul#slideshowTabsDummy li").eq(nextTabIndex).click();
				// User has selected the tab and it's the last slide in this group, loop back to start of group
				} else if ($("ul#slideshowTabs").data("tabUserSelected") == true || !multipleSlideshows) {
					currentSlideIndex = 0;
					loadSlideContent(currentSlideIndex);
				}
				Cufon.replace('#slideshowTabs h4',{hover: true,fontFamily: 'VAG Rounded'});
				// LoadContent(currentSlideIndex);
				return false;
			}
			
			// Play/pause
			var togglePlay = function() {
				autoPlay = !autoPlay;
				$(this).toggleClass("pause", autoPlay);					
				autoPlay ? startTimer() : pauseTimer();
				return false;
			}
			
			// Play
			var playSlideshow = function() {
				autoPlay = true;
				$playBtn.toggleClass("pause", autoPlay);
				startTimer();
			}
			// Triggered by tabs
			this.playSlideshow = playSlideshow;
			
			// Pause
			var pauseSlideshow = function() {
				autoPlay = false;
				$playBtn.toggleClass("pause", autoPlay);
				pauseTimer();
			}
			
			// Reset slideshow, triggered by tabs
			this.resetSlideshow = function() {
				autoPlay = false;
				currentSlideIndex = 0;
				loadSlideContent(currentSlideIndex);
				$playBtn.toggleClass("pause", autoPlay);
				resetTimer();
			}
						
			// On button over
			var buttonOver = function() {
				$(this).addClass("buttonOver");
			}
			
			// On button out
			var buttonOut = function() {
				$(this).removeClass("buttonOver");
			}
			
			// Update text box
			var updateText = function(e) {
				if (!$textBox.data("visible")) {
					$textBox.data("visible", true);
					var text = $items[currentSlideIndex].find(">div:first").html();
					if (text && text.length > 0) {			
						fadeInText(text);
					}					
				}
			}
			
			// Reset text box
			var resetText = function() {
				$textBox.data("visible", false).stop(true).css({opacity:0});
			}
			
			// Fade in text effect
			var fadeInText = function(text) {
				$innerText.html(text);
				$textBox.stop(true).animate({opacity:1}, captionSpeed,
					function () {  									
						if (ie) { 
							this.style.removeAttribute('filter'); 
						}
					});  
			}
			
			// Load current content
			var loadSlideContent = function(i) {
				// Select thumb
				$slideshowList.filter(".current").removeClass("current");				
				$($slideshowList.get(i)).addClass("current");
				
				// Reset text
				resetText();
				
				// Set link
				var $currLink = $items[i].find(">a:nth-child(2)");
				var href = $currLink.attr("href");
				if (href) {					
					$imageLink.unbind("click").css({cursor:"pointer"}).attr({href:href, target:$currLink.attr("target")});
				}
				else {
					$imageLink.click(preventDefault).css({cursor:"default"});
				}
				
				// Load image
				if ($items[i].data("img")) {
					$preloader.hide();	
					fadeInContent($items[i].data("img"));
				}	
				else {	
					// Load new image
					var $img = $("<img class='mainImage'/>");
					$img.attr("src", $items[i].data("imgurl"));								
					if (!$img[0].complete) {
						$preloader.show();
						$img.load(
							function() {
								$preloader.hide();
								storeImg($items[i], $(this));
								fadeInContent($(this));
							}
						).error(
							function() {
								alert("Error loading image");
							}
						);
					}
					else {
						$preloader.hide();
						storeImg($items[i], $img);
						fadeInContent($img);
					}
				}	    
			}
			
			// Display content (fade effect)
			var fadeInContent = function($img) {
				$("img#currentImage", $imageLink).stop(true, true);
				$("img.mainImage", $imageLink).removeAttr("id").css("z-index", 0);
				$img.attr("id", "currentImage").css("z-index", 1).stop(true, true).fadeIn(transitionSpeed, 
					function() {
						$("img.mainImage:not('#currentImage')", $imageLink).hide();
						$currentSlideshow.trigger(TEXT_EVENT);
						startTimer();
					}
				);	
			}
			
			// Load image
			var loadImg = function(loadIndex) {
				var $item = $items[loadIndex];
				var $img = $("<img class='mainImage'/>");
				$img.attr("src", $item.data("imgurl"));
				$img.load(function() {
							if (!$item.data("img")) {
								storeImg($item, $(this));
							}
							loadIndex++
							if (loadIndex < $items.length) {
								loadImg(loadIndex);
							}
						})
					.error(function() {
							// Error loading image, continue next
							loadIndex++
							if (loadIndex < $items.length) {
								loadImg(loadIndex);
							}
						});
			}
			
			// Process & store image
			var storeImg = function($item, $img) {
				$imageLink.append($img);
				$item.data("img", $img);
			}
			
			// Start timer
			var startTimer = function() {
				resetTimer();
				if (autoPlay && timerId == null) {
					var transitionSpeed = Math.round($timer.data("pct") * displayTime);
					$timer.animate({width:(slideshowWidth-270)}, transitionSpeed);
					timerId = setTimeout(nextSlide, transitionSpeed);					
				}
			}
			
			// Reset timer
			var resetTimer = function() {
				clearTimeout(timerId);
				timerId = null;
				$timer.stop(true).width(0).data("pct", 1);
			}
			
			// Pause timer
			var pauseTimer = function() {
				clearTimeout(timerId);
				timerId = null;
				var pct = 1 - ($timer.width()/(slideshowWidth+2));
				$timer.stop(true).data("pct", pct);
			}
			
			// Prevent default behavior
			var preventDefault = function() {
				return false;
			}
						
		}		
			
		// Return pos number
		var returnPosNumber = function(value, defaultValue) {
			if (!isNaN(value) && value > 0) {
				return value;
			}
			return defaultValue;
		}
		
		// Return non-neg number
		var returnNonNegNumber = function(value, defaultValue) {
			if (!isNaN(value) && value >= 0) {
				return value;
			}
			return defaultValue;
		}
		
		var defaults = { 
			autoPlay:true,
			mouseoverPause:true,
			displayTime:5000,
			transitionSpeed:800,
			captionSpeed:800,
			timerDisplay:true,
			timerOpacity:0.5,
			singleSlideshow:false
		};
		
		var options = $.extend({}, defaults, params);	
			
		return this.each(
			function() {
				slideshow[slideshowInstance] = new Slideshow($(this), options, slideshowInstance);
				slideshow[slideshowInstance].init();
				slideshowInstance++;
			}
		);
		
	}
	
})(jQuery);
