/**
 * jQuery Slider Plugin
 * @author Rodrigo Zane Arthuso - contact@arthuso.com - http://arthuso.com
 * @version 0.3-custom - 02/05/2011
 *
 * @TODO:
 *	- Calc navigation buttons' width and height (Currently set manually)
 *	- Set animation options (Fade, slide, disable animation, ...)
 *	- Improve and clean code
 *	- Publish code at http://blog.arthuso.com | http://projects.arthuso.com
 *
 * Versions:
 * 0.3-custom (02/05/2011)
 *  - Cleaned code
 *  - Added more custom settings
 *	This is a custom version for cgcanada.com, which includes thumbnail support
 *	and custom functionality.
 * 0.2 (08/13/2010)
 *  - Fixed compatibility with IE 6 and IE 7
 *  - Improved code
 * 0.1 (09/17/2009)
 *	- First Version
 **/

(function($) {

	$.fn.slider = function(options) {

		var settings = $.extend({
			interval: 10000,
			slideSpeed: 1000,
			start: 0,
			pauseOnMouseOver: false,
			useNavigationButtons: true,
			navigationClasses: new Array("slider-prev", "slider-next"),
			autoHideNav: true,
			thumbIdentifier: "thumb",
			captionClass: "caption"
		}, options);

		return this.each(function(){

			var slide = $(this);
			var items = $("li", slide);
			var total = items.length - 1;
			var has_caption, has_thumbs, has_nav = false;
			var next, timer;

			//  Get width and height of first element
			var width = $(items[0]).width();
			var height = $(items[0]).height();

			$(items).each(function(i){ $(items[i]).attr("id", "s_" + $.slider.randId(5) + "_" + i); });
			
			// Wrap slider container
			$(slide).wrap("<div class='slider_container' style='width:" + width + "px; height:" + height + "px;'></div>");
			
			if (settings.useNavigationButtons) {
				if (settings.navigationClasses instanceof Array && settings.navigationClasses.length == 2) {
					$(slide).after($.slider.placeNavButtons(settings.autoHideNav, settings.navigationClasses, height, width));
					has_nav = true;
				}
			}

			if ($(slide).find("div." + settings.captionClass).length > 0) {
				// Set caption width
				$(slide).find("div." + settings.captionClass).each(function() {
					$(this).width(width - (parseInt($(this).css("paddingLeft")) + parseInt($(this).css("paddingRight"))));
				});
				
				has_caption = true;
			}
			
			if (settings.thumbIdentifier && settings.thumbIdentifier != "") {
				$(slide).after("<ul class='slider_thumbnails'></ul>");
				
				var thumbnails = new Array();
				var itemId, itemSrc, itemSrcExtIndex, thumbSrc;
				
				$(items).each(function(i){
					itemId = $(items[i]).attr("id");
					itemSrc = $(items[i]).find("img").attr("src");
					itemSrcExtIndex = itemSrc.indexOf(".");
					thumbSrc = itemSrc.slice(0, itemSrcExtIndex) + "_" + settings.thumbIdentifier + ".png"; // using png as default for now
					thumbnails[i] = '<li id="' + settings.thumbIdentifier + itemId + '"';
					
					if (i == 0) {
						thumbnails[i] += ' class="' + settings.thumbIdentifier + '_first"';
					} else if (i == total) {
						thumbnails[i] += ' class="' + settings.thumbIdentifier + '_last"';
					}
					
					thumbnails[i] += '><a href="javascript:void(0);"><img src="' + thumbSrc + '" alt="" /></a>';
					thumbnails[i] += '</li>';
				});
				
				if (thumbnails.length > 0) {
					$(thumbnails).each(function(i) {
						$("ul.slider_thumbnails").append(thumbnails[i]);
					});
					
					has_thumbs = true;
				}
			}

			// Start
			skip((settings.start > total) ? 0 : settings.start);

			// Watch for navigation buttons click
			if (has_nav) {
				// Skip to previous item
				$(slide).siblings("." + settings.navigationClasses[0]).click(function() {
					skip(getNext(getIdActive(), "prev"), true);
				});
				// Skip to next item
				$(slide).siblings("." + settings.navigationClasses[1]).click(function() {
					skip(getNext(getIdActive()), true);
				});
			}
			
			// Watch for thumbs click
			if (has_thumbs) {
				$("ul.slider_thumbnails li a").click(function() {
					var showItemId = parseInt($(this).parent().attr("id").replace(/[^0-9]+/g, ''));
					skip(showItemId, false);
				}).hover(function() {
					if ($(this).children("img").attr("src").indexOf("_hover") == -1) $(this).children("img").attr("src", $(this).children("img").attr("src").replace(".png", "_hover.png"));
				}, function() {
					if (!$(this).parent().hasClass(settings.thumbIdentifier + "active")) $(this).children("img").attr("src", $(this).children("img").attr("src").replace("_hover", ""));
				});
			}

			// Pause on mouse over
			if (settings.pauseOnMouseOver) {
				$(slide).hover(function() {
					pause();
				}, function() {
					queue(getNext(getIdActive()));
				});
			}

			// Toggle display of nav buttons on mouse over
			if (has_nav && settings.autoHideNav) {
				$(slide).parent().hover(function() {
					$(slide).siblings("." + settings.navigationClasses[0] + ", ." + settings.navigationClasses[1]).fadeIn();
				}, function() {
					$(slide).siblings("." + settings.navigationClasses[0] + ", ." + settings.navigationClasses[1]).fadeOut();
				});
			}

			/**
			 * queue()
			 * Slider engine - Queue next item
			 * @param id Id of item to be shown
			 */
			function queue(id) {
				timer = window.setTimeout(function(){
					// Move item
					move(id);
					// Queue next item
					queue(getNext(id));
				}, settings.interval);
			}

			/**
			 * move()
			 * @param id_curr Id of current item
			 */
			function move(id_curr) {
				// Hide nav buttons while moving items
				if (has_nav) $(slide).siblings("." + settings.navigationClasses[0] + ", ." + settings.navigationClasses[1]).fadeOut("fast");

				// Hide previous caption (if present)
				if (has_caption) handleCaption(null, "hide");
				
				// Update thumbs
				if (has_thumbs) handleThumbnail(id_curr);

				if (id_curr == 0) {
					$(slide).css({marginLeft: -(id_curr * width)}).find("li[class='active']").removeClass("active");
					$(items[id_curr]).addClass("active");
					// Show nav buttons after animation is complete
					if (has_nav && !settings.autoHideNav) $(slide).siblings("." + settings.navigationClasses[0] + ", ." + settings.navigationClasses[1]).fadeIn();
					// Display item caption if present
					if (has_caption) handleCaption(id_curr);
				} else {
					$(slide).animate({
						marginLeft:-(id_curr * width)
					}, settings.slideSpeed, function() {
						// Update 'active' class
						$(slide).find("li[class='active']").removeClass("active");
						$(items[id_curr]).addClass("active");
						// Show nav buttons after animation is complete
						if (has_nav && !settings.autoHideNav) $(slide).siblings("." + settings.navigationClasses[0] + ", ." + settings.navigationClasses[1]).fadeIn();
						// Display item caption if present
						if (has_caption) handleCaption(id_curr);
					});
				}
			}

			/**
			 * getNext
			 * Get next item to be shown
			 * @param id Id of current item
			 * @param type Count previous or next
			 */
			function getNext(id, type) {
				switch (type) {
					case "prev": next = (id == 0 ? total : (id - 1));
						break;
					default: next = (id == total ? 0 : (id + 1));
				}
				return next;
			}

			/**
			 * getIdActive()
			 * Returns Id of active item
			 */
			function getIdActive() {
				return parseInt($(slide).find("li[class='active']").attr("id").replace(/[^0-9]+/g, ''));
			}

			/**
			 * skip()
			 * Skip slide item
			 * @param id Id of item to skip to
			 * @param animate Whether animation should be applied
			 */
			function skip(id, animate) {
				// Pause timer
				pause();

				$(slide).find("li[class='active']").removeClass("active");
				$(items[id]).addClass("active");

				if (animate) {
					if (has_nav) $(slide).siblings("." + settings.navigationClasses[0] + ", ." + settings.navigationClasses[1]).fadeOut("fast");
					// Hide previous caption (if present)
					if (has_caption) handleCaption(null, "hide");
					// Update thumbs' border
					if (has_thumbs) handleThumbnail(id);
					
					$(slide).animate({
						marginLeft:-(id * width)
					}, settings.slideSpeed, function() {
						if (has_nav) $(slide).siblings("." + settings.navigationClasses[0] + ", ." + settings.navigationClasses[1]).fadeIn();
						if (has_caption) handleCaption(id);
					});
				} else {
					// Currently, only used when starting slider
					$(slide).css({marginLeft:-(id * width)});
					if (has_caption) handleCaption(id);
					if (has_thumbs) handleThumbnail(id);
				}
				// Queue next item
				queue(getNext(id));
			}

			/**
			 * pause()
			 * Clear timer
			 */
			function pause() {
				clearTimeout(timer);
			}

			/**
			 * handleCaption()
			 * Handles caption (if present in html)
			 * @param id Id of current element
			 * @param action Action to be taken
			 */
			function handleCaption(id, action) {
				switch (action) {
					case "hide": $(slide).find(".caption_active").removeClass("caption_active").slideUp();
						break;
					default:
						var item_caption = $(items[id]).find("div." + settings.captionClass);
						if (item_caption.length > 0) $(item_caption).addClass("caption_active").slideDown();
				}
			}
			
			/**
			 * handleThumbnail
			 * Custom function made for cgcanada.com
			 * Clean me
			 * @param id
			 */
			function handleThumbnail(id) {
				var activeThumbClass = settings.thumbIdentifier + "active";
				var nextItemThumbId = settings.thumbIdentifier + $(items[id]).attr("id");
				var activeThumb = $("ul.slider_thumbnails").find("li." + activeThumbClass);
				var nextThumb = $("ul.slider_thumbnails").find("li[id='" + nextItemThumbId + "']");
				var activeSlide, activeItemImg, activeItemSrc, activeItemSrcExtIndex, activeItemNewSrc, nextItemImg, nextItemSrc, nextItemSrcExtIndex, nextItemNewSrc;
			
				activeThumb.removeClass(activeThumbClass);
				nextThumb.addClass(activeThumbClass);
				
				if (activeThumb.length > 0) {
					activeSlide = $(slide).find("#" + activeThumb.attr("id").replace(settings.thumbIdentifier, "")).find("img");
					activeItemImg = activeThumb.find("img");
					activeItemSrc = activeSlide.attr("src");
					activeItemSrcExtIndex = activeItemSrc.indexOf(".");
					activeItemNewSrc = activeItemSrc.slice(0, activeItemSrcExtIndex) + "_" + settings.thumbIdentifier + ".png"; // using png as default for now
					activeItemImg.attr("src", activeItemNewSrc);
				}

				nextItemImg = nextThumb.children(0).children(0);
				nextItemSrc = nextItemImg.attr("src");
				nextItemSrcExtIndex = nextItemSrc.indexOf(".");
				nextItemNewSrc = nextItemSrc.slice(0, nextItemSrcExtIndex) + "_hover.png";
				if (nextItemNewSrc.indexOf("_hover_hover") != -1) nextItemNewSrc = nextItemNewSrc.replace("_hover_hover", "_hover");
				nextItemImg.attr("src", nextItemNewSrc);
			}

		});

	};

	$.slider = {
		/**
		 * placeNavButtons
		 * Place navigation buttons
		 * @param autoHideNav Whether to hide nav buttons
		 * @param navClasses CSS classes for prev and next buttons
		 * @param height Element's height - necessary to position nav buttons
		 * @param width Element's width - necessary to position nav buttons
		 * @return String buttons
		 */
		placeNavButtons: function(autoHideNav, navClasses, height, width) {
			// update me
			var nav_margin_top = (height/2)-50;
			var nav_margin_right = width-54;
			var buttons;
			
			if (autoHideNav) {
				buttons = "<div class='" + navClasses[0] + "' style='display:none; margin-top:" + nav_margin_top + "px;'></div><div class='" + navClasses[1] + "' style='display:none; margin:" + nav_margin_top + "px 0 0 " + nav_margin_right + "px;'></div>";
			} else {
				buttons = "<div class='" + navClasses[0] + "' style='margin-top:" + nav_margin_top + "px;'></div><div class='" + navClasses[1] + "' style='margin:" + nav_margin_top + "px 0 0 " + nav_margin_right + "px;'></div>";
			}
			
			return buttons;
		},
		
		/**
		 * randId
		 * Returns a random ID / String
		 * @param maxChars
		 * @return random_id
		 */
		randId: function(maxChars) {
			var chars = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,x,w,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,X,W,Y,Z".split(",");
			var random_id = "";
			var chrs = (!isNaN(maxChars) && maxChars > 1) ? maxChars : 6;
			for (i = 0; i < chrs; i++) { random_id += chars[Math.floor(Math.random()*chars.length)]; }
			return random_id;
		}
	};

})(jQuery);
