(function( $ ) {
	$.fn.rssScroller = function(options) {
		// this function is called every n/100th of a second to scroll both divs up a little bit.
		function rssScrollStep()
		{
			
			// move each div up a bit.
			firstScrollingChild.css(
				options["direction"], parseInt(firstScrollingChild.css(options["direction"])) - Math.floor(moveAmount)
			);
			calledElement.children().last().css(
				options["direction"], parseInt(lastScrollingChild.css(options["direction"])) - Math.floor(moveAmount)
			);
			
			
			// if the div has scrolled up out of view, put it at the bottom

			if (parseInt(firstScrollingChild.position().top) + firstScrollingChild.outerHeight(false) < 0)
			{
				calledElement.children().first().css(
					"top", parseInt(lastScrollingChild.css("top")) + 
					lastScrollingChild.outerHeight(true) - topMargin
				);
			}
			if (parseInt(lastScrollingChild.position().top) + lastScrollingChild.outerHeight(false) < 0)
			{
				lastScrollingChild.css(
					"top", parseInt(firstScrollingChild.css("top")) + 
					firstScrollingChild.outerHeight(true) - topMargin
				);
			}

			// pause the boxes if pause has been set
			alreadyScrolled += Math.floor(moveAmount);

			if (options["pause"] && alreadyScrolled >= maxOuterHeight - topMargin )
			{				
				alreadyScrolled = alreadyScrolled - (maxOuterHeight - topMargin);
				myTimer = setTimeout(rssScrollStep, options["pause"]);
			}
			else
			{
				myTimer = setTimeout(rssScrollStep, timerDelay);
			}

		}
		function rssScrollStepLeft()
		{
			// move each div up a bit.
			firstScrollingChild.css(
				options["direction"], parseInt(firstScrollingChild.css(options["direction"])) - Math.floor(moveAmount)
			);
			calledElement.children().last().css(
				options["direction"], parseInt(lastScrollingChild.css(options["direction"])) - Math.floor(moveAmount)
			);
			
			
			// if the div has scrolled up out of view, put it at the bottom

			if (parseInt(firstScrollingChild.position().left) + firstScrollingChild.outerWidth(false) < 0)
			{
				calledElement.children().first().css(
					"left", parseInt(lastScrollingChild.css("left")) + 
					lastScrollingChild.outerWidth(true) - leftMargin
				);
			}
			if (parseInt(lastScrollingChild.position().left) + lastScrollingChild.outerWidth(false) < 0)
			{
				lastScrollingChild.css(
					"left", parseInt(firstScrollingChild.css("left")) + 
					firstScrollingChild.outerWidth(true) - leftMargin
				);
			}

			// pause the boxes if pause has been set
			alreadyScrolled += Math.floor(moveAmount);

			if (options["pause"] && alreadyScrolled >= maxOuterWidth - leftMargin )
			{				
				alreadyScrolled = alreadyScrolled - (maxOuterWidth - leftMargin);
				myTimer = setTimeout(rssScrollStepLeft, options["pause"]);
			}
			else
			{
				myTimer = setTimeout(rssScrollStepLeft, timerDelay);
			}

		}
		
		// begin main code. set dimensions, overflow and position.
  
  		this.height(this.height());
  		this.width(this.width());
		this.css("position", "relative");
		this.css("overflow", "hidden");
		
		var calledElement = this;
	
	
		// set each rss div to height of the largest.
		
		var maxHeight = 0;
		var maxOuterHeight = 0;
		var maxWidth = 0;
		var maxOuterWidth = 0;
		this.children().each(function(){
			maxHeight = Math.max(maxHeight, jQuery(this).height());
			maxOuterHeight = Math.max(maxOuterHeight, jQuery(this).outerHeight(true));
			maxWidth = Math.max(maxWidth, jQuery(this).width());
			maxOuterWidth = Math.max(maxOuterWidth, jQuery(this).outerWidth(true));
		});
		this.children().each(function(){
			jQuery(this).height(maxHeight);	
			jQuery(this).width(maxWidth);				
		});
		
		var topMargin = parseInt(this.children().first().css("margin-top"));
		var leftMargin = parseInt(this.children().first().css("margin-left"));
		
		// wrap the contents of the called element and duplicate it. these two elements will be 
		// positioned and scrolled.

		this.wrapInner("<div>");
		this.append(this.html());
		
		this.children().first().css("position", "absolute");
		this.children().last().css("position", "absolute");
		
		
		this.children().first().css("top", 0);
		this.children().first().css("left", 0);
		
		if ("top" == options["direction"])
		{
			this.children().last().css("top", this.children().first().position().top + this.children().first().outerHeight(true) - topMargin);
			this.children().last().css("left", 0);
		}
		else
		{
			this.children().last().css("top", 0);
			this.children().last().css("left", this.children().first().position().left + this.children().first().outerWidth(true) - leftMargin);
		}
		
		// math to calculate the timer delay according to fps. 
		// math to calculate move amount according to speed, fps and the height of the child elements calculated above.
		var timerDelay = Math.floor(1000 / options["fps"]);
		var moveAmount = 0;
		if ("top" == options["direction"])
		{
			moveAmount = maxHeight / options["fps"] / (options["speed"] / 1000);
		}
		else
		{
			moveAmount = maxWidth / options["fps"] / (options["speed"] / 1000);
		}
		// already scrolled is used to store how much has scrolled so it can be used to detect when we should delay.
		var alreadyScrolled = 0;
		var firstScrollingChild = this.children().first();
		var lastScrollingChild = this.children().last();
		
		// call main scroll function! it's recursive, sets a timer to call itself after timerDelay milliseconds.
		if ("top" == options["direction"])
		{
			rssScrollStep();
		}
		else
		{
			rssScrollStepLeft();
		}
		// pause and resume scrolling according to mouse movement.
		var moveAmountBackup = 0;
		this.mouseenter(
			function(){
				moveAmountBackup = moveAmount;
				moveAmount = 0;
			}
		);
		this.mouseleave(
			function(){
				moveAmount = moveAmountBackup;
			}
		);

	};
})( jQuery );



