/*
@todo	check jquery ease plugin to ease the scrolling
@todo	make sure we can have multiple instances on one page
@todo	support auto width and height to auto calculate available space and resize
		
@note	if marquee is horizontal, make sure the li's have a width set in the css
*/
(function($){
	$.fn.marquee = function(options) {

		var defaults = {
			buttons: true,
			controls: true,
			direction: 'bt'
		};

		var options = $.extend(defaults, options);

		return this.each(function() {
			// save reference to this
			var self = $(this);
			
			// attributes
			var axis = 'x';
			var blocks = [];
			var containerHeight = 0;
			var containerWidth = 0;
			var liHeight = 0;
			var liWidth = 0;
			var nofLis = 0;
			var timeout;
			var ul = self.find('ul');
			var ulHeight = 0;
			var ulWidth = 0;
			
			autorotate = function() {
				rotate({autorotate:true});
			}
			
			init = function() {
				if (!$(ul).find('li').length) return;
				
				setAxis();
				setDimensions();
				setBlocks();
				setControls();
				autorotate();
			}
			
			// rotate
			rotate = function(parms) {
				switch (options.direction) {
					case 'bt':	default_direction = 'up';		break;
					case 'tb':	default_direction = 'down';		break;
					case 'lr':	default_direction = 'right';	break;
					case 'rl':	default_direction = 'left';		break;
					default: alert("Direction ("+options.direction+") not supported.\nValid options are bt, tb, lr and rl."); return;
				}
				var parms = $.extend({direction:default_direction, distance:1, autorotate:false}, parms);
				
				switch(parms.direction) {
					case 'down':
						$(blocks).each(function(){
							var position = $(this).position();
							
							// append item to bottom if item ends beyond top boundary of ul
							if (position.top > containerHeight) {
								$(this).css({top: position.top + parms.distance - (blocks.length * ulHeight) + 'px'});
							}
							else {
								$(this).css({top: position.top + parms.distance + 'px'});
							}
						});
						break;
						
					case 'left':
						$(blocks).each(function(){
							var position = $(this).position();
							
							// append item to right if item ends beyond left boundary of ul
							if ((position.left + ulWidth - parms.distance) < 0) {
								$(this).css({left: position.left - parms.distance + (blocks.length * ulWidth) + 'px'});
							}
							else {
								$(this).css({left: position.left - parms.distance + 'px'});
							}
						});
						break;
						
					case 'right':
						$(blocks).each(function(){
							var position = $(this).position();
							
							// append item to left if item ends beyond right boundary of ul
							if ((position.left + parms.distance) > containerWidth) {
								$(this).css({left: position.left + parms.distance - (blocks.length * ulWidth) + 'px'});
							}
							else {
								$(this).css({left: position.left + parms.distance + 'px'});
							}
						});
						break;
						
					case 'up':
						$(blocks).each(function(){
							var position = $(this).position();
							
							// append item to bottom if item ends beyond top boundary of ul
							if ((position.top + ulHeight - parms.distance) < 0) {
								$(this).css({top: position.top - parms.distance + (blocks.length * ulHeight) + 'px'});
							}
							else {
								$(this).css({top: position.top - parms.distance + 'px'});
							}
						});
						break;
				}
				
				if (parms.autorotate) {
					timeout = setTimeout(function(){rotate(parms)}, 40);
				}
			}
			
			setAxis = function() {
				axis = (options.direction == 'tb' || options.direction == 'bt') ? 'y' : 'x';
			}
			
			setBlocks = function(parms) {
				// position absolute
				$(ul).css({position:'absolute'});
				
				// horizontal scroll
				if (axis == 'x') {
					// display li's inline
					var lis = $(ul).find('li');
					lis.each(function(j){
						$(this).css({display:'inline', position:'absolute', left: j * liWidth + 'px'});
					});
					
					// set new ul width based on width of li's
					ulWidth = lis.length * liWidth;
					
					// create blocks to move ul instead of moving each li individually for performance reasons (at least 2 to prevent boundary problems)
					var copies = Math.ceil(containerWidth / ulWidth);
					
					// create copies
					for (var i=copies; i>0; i--) {
						var ulcopy = ul.clone();
						self.append(ulcopy);
					}
					
					// now get all ul's including copies to position
					blocks = self.find('ul');
					
					// put ul's next to eachother
					$(blocks).each(function(i) {
						$(this).css({left: i * ulWidth});
					});
				}
				
				// vertical scroll
				if (axis == 'y') {
					// create blocks to move ul instead of moving each li individually for performance reasons (at least 2 to prevent boundary problems)
					var copies = Math.ceil(containerHeight / ulHeight);

					// create copies
					for (var i=copies; i>0; i--) {
						var ulcopy = ul.clone();
						self.append(ulcopy);
					}
					
					// now get all ul's including copies to position
					blocks = self.find('ul');
					
					// put ul's below eachother
					$(blocks).each(function(i) {
						$(this).css({top: i * ulHeight + 'px'});
					});
				}
			}
			
			setControls = function() {
				$(self).on('mouseover', function() {
					clearTimeout(timeout);
				});
				
				$(self).on('mouseout', function() {
					autorotate(options);
				});
				
				$('#down').on('click', function(){
					clearTimeout(timeout);
					rotate({direction:'down', distance:20});
				});
				
				$('#left').on('click', function(){
					clearTimeout(timeout);
					rotate({direction:'left', distance:50});
				});
				
				$('#right').on('click', function(){
					clearTimeout(timeout);
					rotate({direction:'right', distance:50});
				});
				
				$('#up').on('click', function(){
					clearTimeout(timeout);
					rotate({direction:'up', distance:20});
				});
			}
			
			setDimensions = function() {
				// set container dimensions
				containerHeight = self.outerHeight();
				containerWidth = self.outerWidth();
				
				// set ul dimensions (note, ulWidth might be overwritten in horizontal mode in position() function)
				ulHeight = $(ul).outerHeight();
				ulWidth = $(ul).outerWidth();
				
				// set item dimensions, note: we expect all items to have the same dimensions
				liHeight = $(ul).find('li').first().outerHeight();
				liWidth = $(ul).find('li').first().outerWidth();
				
				// nof items
				nofLis = $(ul).find('li').length;
			}
			
			init();
		});
	};
})(jQuery);
