//prevent errors in browsers that do not support console.
if (typeof window.loadFirebugConsole == "undefined" || typeof window.console == 'undefined' ) {
  var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
  window.console = {};
  for (var i = 0; i < names.length; ++i) {
    window.console[names[i]] = function(){};
  }
}
(function($) {
	$.fn.scRotator = function(options){
		// Default settings.
		var defaults = {
			speed: 1000,
			auto: true,
			continuous: true,
			pause: 1000,
			fade: true,
			controls: true,
			controlsPrefix: 'controls',
			controlsCssClass: 'control'
		};
		var options = $.extend(defaults, options);
		
		// Main "function".
		return this.each(function() {
			var obj = $(this);
			var _internalId = obj.attr('id');
			var s = $("li", obj).length;
			var w = $("li", obj).width();
			var h = $("li", obj).height();
			var clickable = true;
			obj.width(w);
			obj.height(h);
			obj.css("overflow", "hidden");
			var ts = s-1;
			var t = 0;
			var continuous = options.continuous;
			
			$("ul", obj).css('width', (s+1)*w);
			
			// Organize list depending on run mode (slide or fade).
			if (!options.fade) {
				$("li", obj).css('float', 'left');
			} else {
				$("li", obj).css('display', 'none');
				$("li:first", obj).css('display', 'block');
			}
			
			if (s > 1) {
				$("li", obj).mouseover(mouseoverCallback).mouseout(mouseoutCallback);
			}
			
			options.controls = (options.controls && s > 1) ? true : false;
			
			if (options.controls) {
				setupControls();
			}
			
			function mouseoverCallback() {
				clearTimeout(timeout);
			}
			
			function mouseoutCallback() {
				timeout = initTimeout(getPauseInterval(t));
			}
			
			// Initialize controls.
			function setupControls() {
				var controlsHtml = '<ol id="' + options.controlsPrefix + '" class="' + options.controlsCssClass + '"></ol>';
				$(obj).after(controlsHtml);
				for (var i=0; i < s; i++) {
					$(document.createElement("li"))
						.attr('id',options.controlsPrefix + (i+1))
						.html('<a rel='+ i +' href="javascript:void(0);">'+ (i+1) +'</a>')
						.appendTo($("#"+ options.controlsPrefix))
						.click(function() {
							run($("a",$(this)).attr('rel'), true);
						});
				}
			}
			
			// Highlight current control.
			function setCurrent(i){
				i = parseInt(i)+1;
				$("li", "#" + options.controlsPrefix).removeClass("current");
				$("li#" + options.controlsPrefix + i).addClass("current");
			}
			
			function initTimeout(timer) {
				return setTimeout(function() {
					run("next", false);
				}, timer);
			}
			
			// For sliding adjust margin.
			function adjust() {
				init();
				$("ul", obj).css("margin-left", (t*w*-1));
			}
			
			// Reset some values and set clickable again.
			function init() {
				if (t > ts) t = 0;
				if (t < 0) t = ts;
				t = parseInt(t);
				initControls();
			}
			
			function initControls() {
				clickable = true;
				setCurrent(t);
			}
			
			// Slide contents.
			// TODO: Implement correctly. Due to heavy changes around this may not work anymore.
			function slide(t, ot, clicked) {
				var diff = Math.abs(ot-t);
				var speed = diff*options.speed;
				p = (t*w*-1);
				$("ul", obj).animate(
					{ marginLeft: p },
					{ queue: false, duration: speed, complete: adjust }
				);
				if (clicked) clearTimeout(timeout);
				if (options.auto && !clicked) {
					var timer = speed;+getPauseInterval(ot);
					timeout = initTimeout(timer);
				}
			}
			
			// Fade contents. Always fade to white/background color.
			function fade(ot, clicked) {
				var nt = (t <= ts) ? t : 0;
				// When clicked no animation needed.
				if (clicked) {
					$($("ul li", obj)[ot]).hide();
					$($("ul li", obj)[nt]).show();
					setupFade(ot, clicked);
				} else {
					$("li", obj).unbind("mouseover").unbind("mouseout");
					$($("ul li", obj)[ot]).fadeOut(options.speed, function() {
						// Move to the end and fade in next element.
						$($("ul li", obj)[nt]).fadeIn(options.speed, setupFade(ot, clicked));
					});
				}
			}
			
			// To be aware of sequential processing this callback is needed.
			function setupFade(ot, clicked) {
				init();
				$("li", obj).mouseover(mouseoverCallback).mouseout(mouseoutCallback);
				var speed = options.speed;
				if (clicked) clearTimeout(timeout);
				if (options.auto && !clicked) {
					// The actual/reset t has to be used. Set in init above.
					var timer = speed+getPauseInterval(t);
					timeout = initTimeout(timer);
				}				
				
			}
			
			// Get actual pause interval. Maybe a global value or an array.
			function getPauseInterval(t) {
				var pause;
				if (isNaN(options.pause) && options.pause instanceof Array) {
					pause = options.pause[t];
				} else {
					pause = parseInt(options.pause);
				}
				return pause;
			}
			
			// Run the rotator.
			function run(dir, clicked) {
				if (clickable) {
					clickable = false;
					var ot = t;
					switch(dir) {
						case "next":
							t = (ot >= ts) ? ((continuous) ? t+1 : ts) : t+1;
							break;
						case "prev":
							t = (t <= 0) ? ((continuous) ? t-1 : 0) : t-1;
							break;
						case "first":
							t = 0;
							break;
						case "last":
							t = ts;
							break;
						default:
							t = dir;
							break;
					}
					if (!options.fade) {
						slide(t, ot, clicked);
					} else {
						fade(ot, clicked);
					}
				}
			}
			
			var timeout;
			
			// Autostart rotator. Called once on load.
			if (options.auto && s > 1) {
				timeout = initTimeout(getPauseInterval(t));
			};
			if (options.controls) {
				setCurrent(t);
			}
			
			function log(message) {
				console.log("[" + _internalId + "] - (" + arguments.callee.caller.name + ") - " + message);
			}
		});
	}
})(jQuery);
