(function($){
	
	$.fn.scroll = function(input)
	{
		if(input === undefined || input === null) {
			input = {};
		}
		
		if(typeof input == 'object')
		{
			input = $.extend({}, $.fn.scroll.defaults, input);
			
			if(input.direction != 'left' && input.direction != 'right' &&
			   input.direction != 'up' && input.direction != 'down') 
			{
				input.direction = 'left';
			}
			
			if(input.delta < 50) {
				input.delta = 50;
			}
			
			if(input.direction == 'right' || input.direction == 'down') {
				input.delta *= -1;
			}
			
			if(input.frequency < 0) {
				input.frequency = 0;
			}
		}
				
		return this.each(function(){
			var $this = $(this);
			
			if(typeof input == 'object')
			{
				var options = input;
			
				$this.data('options', options);
								
				$.fn.scroll.setUp($this);
			}
			else if(typeof input == 'string')
			{
				var options = $this.data('options');
			
				if(options !== undefined && options !== null)
				{
					if(input == 'start')
					{
						if(options.frequency > 0) {
							options.timeoutId = setTimeout(function(){ $.fn.scroll.doScroll($this); }, options.frequency);
						} else {
							$.fn.scroll.doScroll($this);
						}
					}
					else if(input == 'stop')
					{
						$this.stop();
						
						if(options.timeoutId !== null)
						{
							clearTimeout(options.timeoutId);
							options.timeoutId = null;
						}
					}
					
					$this.data('options', options);
				}
			}
		});
	};
	
	$.fn.scroll.defaults = {
		checkImageLoad: true,
		direction: 'left', // The direction to scroll
		selector: '> *', // The selector used to find items to move
		delta: 100, // The amount of pixels to move
		speed: 1000, // The amount of time over which to move
		auto: true, // Should the scroller scroll on it's own
		frequency: 0, // How much time is there between each scroll
		border: null, // The position where the scrolling objects go out of bounds
		spacing: 0, // The amount of space to put between each item
		easing: 'linear', // The easing function to be used
		afterSetUp: null, // A callback function after the scroller has set up
		timeoutId: null
	};
	
	$.fn.scroll.setUp = function($this) {
		var options = $this.data('options');
		
		if(options !== undefined && options !== null)
		{
			$items = $(options.selector, $this);
						
			var check = true;
			
			if(options.checkImageLoad)
			{
				$images = $('img, image', $this);
							
				$images.each(function()
				{
					if(check)
					{
						var $image = $(this);
						
						if(!this.complete || $image.width() == 0 || $image.height() == 0) {
							setTimeout(function(){ $.fn.scroll.setUp($this); }, 500);
							check = false;
						}
					}
				});
			}
			
			if(check)
			{
				$this.css('position', 'relative').css('overflow', 'hidden');
			
				var pos = 0;
				
				if(options.direction == 'left' || options.direction == 'right')
				{
					$items.each(function(){
						var $this2 = $(this);
						$this2.css('position', 'absolute').css('left', pos + 'px');
						pos += $this2.width() + options.spacing;
					});
				}
				else if(options.direction == 'up' || options.direction == 'down')
				{
					$items.each(function(){
						var $this2 = $(this);
						$this2.css('position', 'absolute').css('top', pos + 'px');
						pos += $this2.height() + options.spacing;
					});
				}
				
				$this.html('<div></div>');
				
				$div = $('> div', $this).css('position', 'absolute').css('left', 0).append($items).css('width', pos);
				$div2 = $div.clone().css('position', 'absolute').css('left', $div.width()).css('width', pos);
				
				$this.append($div2);
					
				if(options.direction == 'right') {
					$this.attr('scrollLeft', pos);
				}
				
				if(options.direction == 'down') {
					$this.attr('scrollTop', pos);
				}
				
				if(options.border === null)
				{
					if(options.direction == 'left' || options.direction == 'up') {
						options.border = 0;
					} else if(options.direction == 'right') {
						options.border = $this.width();
					} else if(options.direction == 'down') {
						options.border = $this.height();
					}
				}
				
				$this.data('options', options);
				
				if(options.auto)
				{
					if(options.frequency > 0) {
						options.timeoutId = setTimeout(function(){ $.fn.scroll.doScroll($this); }, options.frequency);
					} else {
						$.fn.scroll.doScroll($this);
					}
				}
				
				$this.data('options', options);
				
				if(options.afterSetUp !== null) {
					options.afterSetUp();
				}
			}
		}
	};
	
	$.fn.scroll.doScroll = function($this) {
		var options = $this.data('options');
		
		if(options !== undefined && options !== null)
		{
			var $divs = $('> div', $this);
		
			if(options.direction == 'left' || options.direction == 'right')
			{
				$this.animate({
					scrollLeft: $this.attr('scrollLeft') + options.delta
				}, options.speed, options.easing, function() {
					var width = $divs.eq(0).width();
					var left = $this.attr('scrollLeft');
					
					if(options.direction == 'left')
					{	
						if(left >= width) {
							$this.attr('scrollLeft', left - width);
						}
					} else {
						if(left <= width - $this.width()) {
							$this.attr('scrollLeft', left + width);
						}
					}
					
					if(options.auto) {
						if(options.frequency > 0) {
							options.timeoutId = setTimeout(function(){ $.fn.scroll.doScroll($this); }, options.frequency);
						} else {
							$.fn.scroll.doScroll($this);
						}
					}
				});
			}
			else
			{
				$this.animate({
					scrollTop: $this.attr('scrollTop') + options.delta
				}, options.speed, options.easing, function()
				{
					var height = $divs.eq(0).height();
					var top = $this.attr('scrollTop');
					
					if(options.direction == 'up')
					{
						if(top >= height) {
							$this.attr('scrollTop', top - height);
						}
					}
					else
					{
						if($this.attr('scrollTop') <= height - $this.height()) {
							$this.attr('scrollTop', top + height);
						}
					}
					
					if(options.auto)
					{
						if(options.frequency > 0) {
							options.timeoutId = setTimeout(function(){ $.fn.scroll.doScroll($this); }, options.frequency);
						} else {
							$.fn.scroll.doScroll($this);
						}
					}
				});
			}
		}
	};
	
})(jQuery);