(function($) {
	$.slider = function() { };

	$.slider.init = function(options) {
		
		var defaults = {
			activeClassName: "current",
			slideMethod: "default",
			fadeSpeed: "fast",
			delay: 2000,
			autoPlay: false,
			roundTrip: true,
			repeat: true,
			startSlide: 'random',
			buttons: {
				next: ".next",
				previous: ".previous",
				play: ".play",
				stop: ".stop"
			},
			container: {
				main: "#slides",
				shortcuts: "#shortcuts",
				controller: "#controller"
			}
		};

		var options = $.extend(defaults, options);
		var playing = false;
		
		/**
		 * Determine starting slide
		 * @return int starting slide index
		 */
		var getStartingSlide = function() {

			var slidesCount = getSlidesCount();
			var startSlide = options.startSlide;

			if(startSlide == "random") return Math.floor(Math.random()*slidesCount);
			else if(options.startSlide >= slidesCount) return (slidesCount - 1);
			else if(options.startSlide < 1) return 0;
			else return options.startSlide;
		};

		/**
		 * @return int index of current slide
		 */
		var getCurrentSlideIndex = function() {
			return $(options.container.main).children("div:visible").index();
		};

		/**
		 * @return int next slide index
		 */
		var getNextSlideIndex = function() {
			if((getCurrentSlideIndex() + 2) > getSlidesCount())
			{
				if(options.roundTrip == true) return 1;
				else return false;
			}
			else
			{
				return (getCurrentSlideIndex() + 2);
			}
		};

		/**
		 * @return int previous slide index
		 */
		var getPreviousSlideIndex = function() {
			if(getCurrentSlideIndex() < 1)
			{
				if(options.roundTrip) return getSlidesCount();
				else { return false; }
			}
			else
			{
				return getCurrentSlideIndex();
			}
		};

		/**
		 * @return int total slides count
		 */
		var getSlidesCount = function() {
			return $(options.container.main).children("div.slide").length;
		};
		
		/**
		 * @return boolean 
		 */
		var slideIndexExists = function(slideIndex) {
			var index = $(options.container.main + " div.slide:nth-child(" + slideIndex + ")").index();

			if(index < 0) return false;
			else return true;
		};

		var setSlide = function(slideIndex) {
			if(playing) actionController("resetTimer");

			switch(options.slideMethod)
			{
				case "fade":
				{
					fadeToSlide(slideIndex);
					break;
				}

				default:
				{
					gotoSlide(slideIndex);
					break;
				}
			}

			$(options.container.shortcuts).children("." + options.activeClassName).removeClass(options.activeClassName);
			$(options.container.shortcuts + " a.slide-" + slideIndex).addClass(options.activeClassName);
			
			if(slideIndex == getSlidesCount() && playing && !options.repeat)
			{
				actionController("stop");
			}

			actionController("bindings", slideIndex);

		};

		/**
		 * The function for changing slides fade style using jQuery's .fadeIn/Out()
		 * @param int slideIndex 
		 */
		var fadeToSlide = function(slideIndex)
		{
			$(options.container.main).children("div.slide:visible").fadeOut(options.fadeSpeed);
			$(options.container.main + " div.slide:nth-child(" + slideIndex + ")").fadeIn(options.fadeSpeed);
		};

		/**
		 * Changing slides instantly using jQuery's .hide()
		 * @param int slideIndex
		 */
		var gotoSlide = function(slideIndex) {
			$(options.container.main).children("div.slide:visible").hide();

			$(options.container.main + " div.slide:nth-child(" + slideIndex + ")").show();
		};

		/**
		 * All actions goes through here
		 * @param string action tell the program what do to
		 * @param int index [optional] if action is goto then an index is needed. note that index starts at 0.
		 *
		 * Examples:
		 * <code>
		 * actionController("next"); 
		 * actionController("goto", 1);
		 * </code>
		 */
		var actionController = function(action, index)
		{
			switch(action)
			{
				case "next":
				{
					if(getNextSlideIndex())
					{
						setSlide(getNextSlideIndex());
					}
					else
					{
						return false;
					}
					break;
				}

				case "previous":
				{
					setSlide(getPreviousSlideIndex());
					break;
				}

				case "goto":
				{
					if(slideIndexExists(index))
					{
							setSlide(index);
					}
					else
					{
						
					}
					break;
				}

				case "play":
				{
					$(options.container.controller + " " + options.buttons.play).everyTime(options.delay, function(timer) {
						actionController("goto", getNextSlideIndex());
					});

					unbindPlayButton();
					bindStopButton();

					playing = true;

					$(options.container.controller + " " + options.buttons.play).hide();
					$(options.container.controller + " " + options.buttons.stop).show();

					break;
				}

				case "stop":
				{
					$(options.container.controller + " " + options.buttons.play).stopTime();
					
					bindPlayButton();
					unbindStopButton();

					playing = false;

					$(options.container.controller + " " + options.buttons.play).show();
					$(options.container.controller + " " + options.buttons.stop).hide();

					break;
				}

				case "resetTimer":
				{
					actionController("stop");
					actionController("play");
					
					break;
				}
				
				case "bindings":
				{
				}

				default:
					break;
			}
		};

		/**
		 * We call this method last.
		 * It gathers all the starting functions and variables needed.
		 */
		var startup = function() {
			options.slideMethod="default";

			actionController("goto", getStartingSlide());
			
			options.slideMethod="fade";

			if(options.autoPlay == true)
			{
				actionController("play");
			}
			else
			{
				bindPlayButton();
				$(options.container.controller + " " + options.buttons.stop).hide();
			}
		};
		
		/**
		 * Button assigments
		 */
		var bindPlayButton = function() {
			$(options.container.controller + " " + options.buttons.play).removeClass(options.activeClassName);
			$(options.container.controller + " " + options.buttons.play).attr("disabled", false);
			$(options.container.controller + " " + options.buttons.play).bind("click", function() {
				if(getNextSlideIndex())
				{
					actionController("next");
				}
				else actionController("goto", 1);

				actionController("play");
			});
		};

		var bindStopButton = function() {
			$(options.container.controller + " " + options.buttons.stop).removeClass(options.activeClassName);
			$(options.container.controller + " " + options.buttons.stop).attr("disabled", false);
			$(options.container.controller + " " + options.buttons.stop).bind("click", function() {
				actionController("stop");
			});	
		};
		
		var unbindPlayButton = function() {
			$(options.container.controller + " " + options.buttons.play).addClass(options.activeClassName);
			$(options.container.controller + " " + options.buttons.play).unbind("click");
			$(options.container.controller + " " + options.buttons.play).attr("disabled", true);
			$(options.container.controller + " " + options.buttons.play).addClass(options.activeClassName);
		};

		var unbindStopButton = function() {
			$(options.container.controller + " " + options.buttons.stop).unbind("click");
			$(options.container.controller + " " + options.buttons.stop).addClass(options.activeClassName);
			$(options.container.controller + " " + options.buttons.stop).attr("disabled", true);
		};

		$(options.container.controller + " " + options.buttons.next).click(function() {
			actionController("next");
		});

			$(options.container.controller + " " + options.buttons.previous).click(function() {
			actionController("previous");
		});

		$(options.container.shortcuts + " .slide").bind("click", function() {
			actionController("goto", ($(this).index() + 1));
			actionController("stop");
		});

		startup();
		
	};

})(jQuery);
