"use strict";
/*global jQuery */
(function ($) {
	$.fn.jshow = function (options) {
		var init, setupStage, injectClassnames, assignCurrent, injectControls, createElement, setDimensions, setDimensions_Fade, setDimensions_Scroll,
			pause, play, goTo, findIndex, findNextIndex, findPrevIndex, findItem, updateIndexes, animate, fade, scroll, arrayValueExists,
			container = this,
			innerContainer,
			itemsArray = [],
			counters = {
				currentIndex: 0,
				nextIndex: 1,
				itemCount: 0
			},
			defaults = {
				effect: "fade", // Transition effect ['fade' | 'scroll']
				transitionSpeed: 1000, // Transition speed
				transitionInterval: 4000, // Interval time between transitions
				controls: [] // Slideshow controls to display ['pause', 'first', 'previous', 'items', 'next', 'last']
			},
			settings = $.extend(defaults, options),
			markup = {
				innerContainer: function (effect) {
					return '<div class="inner-container ' + effect + '"></div>';
				},
				controlsContainer: function () {
					return '<div class="controls"><ul></ul></div>';
				},
				controlItem: function (item) {
					return '<li class="control-' + item.type + ((item.classname) ? ' ' + item.classname : '') + '"><a href="#" title="' + item.title + '">' + item.title + '</a></li>';
				}
			},
			allowedControls = {
				fade: ['first', 'previous', 'items', 'next', 'last', 'pause'],
				scroll: ['previous', 'next', 'pause']
			},
			buttonClicked = "", buttonsLocked = false, slideshowPaused = false,
			controlsContainer;
		
		init = function () {
			setupStage();
			play();
		};
		
		setupStage = function () {
			injectClassnames();
			setDimensions();
			injectControls();
		};
		
		injectClassnames = function () {
			$(container).addClass("slideshow-generated");
			$(container).children("DIV").wrapAll(markup.innerContainer(settings.effect));
			innerContainer = $("DIV.inner-container", container);
			$(innerContainer).children("DIV:first").addClass("current").css({"z-index": "2"});
			$(innerContainer).children("DIV").each(function (index) {
				itemsArray.push($(this)[0]);
				$(this).addClass("slide slide-" + (index + 1));
			});
			counters.itemCount = itemsArray.length;
		};
		
		assignCurrent = function () {
			var nextItem = findItem(counters.nextIndex),
				nextControlItem = $(".control-" + (counters.nextIndex + 1));
			$(".current", container).removeClass("current");
			$(nextItem).addClass("current");
			$(nextControlItem, container).addClass("current");
		};
		
		injectControls = function () {
			var item, controls, i, j;
			if (settings.controls !== undefined && settings.controls.length > 0) {
				controlsContainer = $(markup.controlsContainer());
				$(container).append(controlsContainer);
				controls = settings.controls;
				for (i = 0; i < controls.length; i = i + 1) {
					if (arrayValueExists(allowedControls[settings.effect], controls[i])) {
						if (controls[i] === "items") {
							for (j = 1; j <= counters.itemCount; j = j + 1) {
								item = {type: j, title: j, index: j - 1, classname: 'item'};
								createElement(item);
							}
						}
						else {
							item = {type: controls[i], title: controls[i].slice(0, 1).toUpperCase() + controls[i].slice(1)};
							createElement(item);
						}
					}
				}
			}
		};
		
		createElement = function (item) {
			var element = $(markup.controlItem(item));
			$("UL", controlsContainer).append(element);
			
			$(element).click(function () {
				if (!buttonsLocked) {
					buttonClicked = item.type;
					if (item.type === "pause") {
						if ($(this).hasClass("control-pause")) {
							pause();
							$(this).removeClass("control-pause").addClass("control-play").children("A").text("Play").attr("title", "Play");
							slideshowPaused = true;
						}
						else {
							play();
							$(this).removeClass("control-play").addClass("control-pause").children("A").text("Pause").attr("title", "Pause");
							slideshowPaused = false;
						}
					}
					else {
						pause();
						goTo(findIndex(item));
						if (!slideshowPaused) {
							play();
						}
					}
				}
				return false;
			});
		};
		
		setDimensions = function () {
			switch (settings.effect) {
			case "fade":
				setDimensions_Fade();
				break;
			case "scroll":
				setDimensions_Scroll();
				break;
			}
		};
		
		setDimensions_Fade = function () {
			var divsArray = [],
			widest = 0, heighest = 0, i;
			$(innerContainer).css({position: 'relative'});
			$(innerContainer).children("DIV").each(function () {
				var width, height;
				width = $(this).width();
				height = $(this).height();
				if (width > widest) {
					widest = width;
				}
				if (height > heighest) {
					heighest = height;
				}
				$(this).css({
					position: 'absolute',
					top: '0px',
					left: '0px',
					display: 'none'
				});
				divsArray.push(this);
			});
			$(findItem(counters.currentIndex)).show();
			$(innerContainer).width(widest).height(heighest);
			for (i = 0; i < divsArray.length; i = i + 1) {
				$(divsArray[i]).width(widest).height(heighest);
			}
		};
		
		setDimensions_Scroll = function () {
			var divsArray = [],
			widest = 0, heighest = 0, count = 0, fullWidth, i;
			$(innerContainer).children("DIV").each(function () {
				var width, height;
				$(this).css({
					float: 'left'
				});
				width = $(this).width();
				height = $(this).height();
				if (width > widest) {
					widest = width;
				}
				if (height > heighest) {
					heighest = height;
				}
				divsArray.push(this);
				count = count + 1;
			});
			fullWidth = widest * count;
			$(container).css({width: widest, overflow: "hidden", position: "relative"});
			$(innerContainer).css({width: fullWidth, height: heighest, position: "relative", left: 0});
			for (i = 0; i < divsArray.length; i = i + 1) {
				$(divsArray[i]).width(widest).height(heighest);
			}
		};
		
		pause = function () {
			clearInterval(this.interval);
		};

		play = function () {
			this.interval = setInterval(function () {
				goTo();
			}, settings.transitionInterval);
		};

		goTo = function (nextIndex) {
			counters.nextIndex = (nextIndex !== undefined) ? nextIndex : findNextIndex();
			if (counters.currentIndex !== counters.nextIndex) {
				assignCurrent();
				animate();
			}
		};
		
		findIndex = function (item) {
			var index;
			switch (item.type) {
			case "first" :
				index = 0;
				break;
			case "last" :
				index = counters.itemCount - 1;
				break;
			case "previous" :
				index = findPrevIndex();
				break;
			case "next" :
				index = findNextIndex();
				break;
			default :
				index = item.index;
				break;
			}
			return index;
		};
		
		findNextIndex = function () {
			var index = counters.currentIndex + 1;
			index = (index > itemsArray.length - 1) ? 0 : index;
			return index;
		};
		
		findPrevIndex = function () {
			var index = counters.currentIndex - 1;
			index = (index < 0) ? itemsArray.length - 1 : index;
			return index;
		};
		
		findItem = function (index) {
			return itemsArray[index];
		};
		
		updateIndexes = function () {
			counters.currentIndex = counters.nextIndex;
		};

		animate = function () {
			var currentItem = findItem(counters.currentIndex),
				nextItem = findItem(counters.nextIndex);
			buttonsLocked = true;
			
			if (settings.effect === "fade") {
				fade(currentItem, nextItem);
			}
			else if (settings.effect === "scroll") {
				scroll();
			}
			buttonClicked = "";
		};
		
		fade = function (currentItem, nextItem) {
			$(nextItem).css({"z-index": "1"}).show();
			$(currentItem).fadeOut(settings.transitionSpeed, function () {
				$(this).css({"z-index": "0"});
				$(nextItem).css({"z-index": "2"});
				updateIndexes();
				buttonsLocked = false;
			});
		};
		
		scroll = function () {
			var animateTo, blockWidth;
			blockWidth = $(innerContainer).children("DIV.slide:first").width();
			animateTo = blockWidth * -1;
			
			if (buttonClicked === "previous") {
				$(innerContainer).children("DIV.slide:last").prependTo(innerContainer);
				$(innerContainer).css({
					left: blockWidth * -1
				});
				$(innerContainer).animate(
					{left: 0},
					settings.transitionSpeed, function () {
						updateIndexes();
						buttonsLocked = false;
					}
				);
			}
			else {
				$(innerContainer).animate(
					{left: animateTo},
					settings.transitionSpeed, function () {
						$(innerContainer).children("DIV.slide:first").appendTo(innerContainer);
						$(innerContainer).css({
							left: 0
						});
						updateIndexes();
						buttonsLocked = false;
					}
				);
			}
		};
		
		arrayValueExists = function (array, obj) {
			var i;
			for (i = 0; i < array.length; i = i + 1) {
				if (array[i] === obj) {
					return true;
				}
			}
			return false;
		};
		
		init();
	};
}(jQuery));
