/**
 * Copyright (c) 2010 Daylight Studio (http://www.thedaylightstudio.com/)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * $Id: jquery.marquee.js 2010-02-23 David McReynolds
 **/

(function($){
	var Marquee = function(el, o){
		this.options  = {
			speed : 50,
			distance : 3,
		 	direction: 'left',
			elementWidth: null, // used to help IE calculate
			elementHeight: null // used to help IE calculate
		};
		$.extend(this.options, o);
		this.el = el;
		this.timer = null;
		this.pos = null;
		this.elWidth = 0;
		this.elHeight = 0;
		this.boundary = 0;
		
		// cache for convenience
		this.$boundarySelector = $(this.el).parent();
		this.$el = $(this.el);
		this.init();
	}
	$.extend(Marquee.prototype, {
	
		init : function(){
			var _this = this;
			if (this.options.direction == 'up' || this.options.direction == 'left'){
				this.options.distance = 0 - this.options.distance;
			}
			this.pos = (this.options.direction == 'up' || this.options.direction == 'down') ? 'top' : 'left';

			if (this.options.direction == 'up' || this.options.direction == 'down'){
				this.boundary =  this.$boundarySelector.outerHeight();
			} else {
				this.boundary = this.$boundarySelector.outerWidth();
			}

			// set them to absolute position
			this.$el.css({position: 'absolute', left: 0, top: 0});

			// double the size of the elements to show endless scrolling
			this.$el.append(this.$el.children().clone());

			// set the real width of the elements so the float doesn't wrap them
			if (this.options.direction == 'up' || this.options.direction == 'down'){
				this.$el.children().each(function(i){
					_this.elHeight += ((_this.options.elementHeight) ? _this.options.elementHeight : $(this).outerHeight(true));
				});
				this.$el.height(this.elHeight);
			} else {
				this.$el.children().each(function(i){
					_this.elWidth += ((_this.options.elementWidth) ? _this.options.elementWidth : $(this).outerWidth(true));
				});
				this.$el.width(this.elWidth);
			}
			this.start();
		},
	
		start : function(){
			this.stop();
			var _this = this;
			var timerCallback = function(){
				_this._move();
			}
			this.timer = setInterval(timerCallback, this.options.speed);
			$(this.el).trigger('marqueeStarted');
		},
	
		stop : function(){
			clearInterval(this.timer);
			$(this.el).trigger('marqueeStopped');
		},
	
		reset : function(){
			this.$el.css({top:0,left:0});
			$(this.el).trigger('marqueeReset');
			this.start();
		},
		
		_move : function(){

			var currentPos = parseInt(this.$el.css(this.pos));
			var newPos = currentPos + this.options.distance;
			var diff = this.options.distance;
			if (this.options.direction == 'left'){
				if (Math.abs(newPos) > (this.elWidth/2)){
					newPos = 0 + diff;
				}
			} else if (this.options.direction == 'right') {
				if (newPos >= 0){
					newPos = -(this.elWidth/2) + diff;
				}
			} else if (this.options.direction == 'up') {
				if (Math.abs(newPos) > this.boundary){
					newPos = 0 - diff;
				}
			} else if (this.options.direction == 'down') {
				if (newPos >= 0){
					newPos = -(this.elHeight/2) + diff;
				}
			}			
			this.$el.css(this.pos, newPos + 'px');
			
		}

		
	});

	$.fn.extend({
		startMarquee : function() {
			return _w.call(this, 'start');
		},
		stopMarquee : function()	{
			return _w.call(this, 'stop');
		},
		resetMarquee : function() {
			return _w.call(this, 'reset');
		}
	});

	function _w(method, args){
		return this.each(
			function(i) {
				var c = _getController(this);
				if (c) {
					if (args){
						return c[method].apply(c, args);
					} else {
						return c[method]();
					}
				}
			}
		);
	}
	function _getController(el)
	{
		if (el._ssId) return $.event._ssCache[el._ssId];
		return false;
	};

	jQuery.fn.marquee = function(o) {
		if (!$.event._ssCache) $.event._ssCache = [];
	
		return this.each(function(i){
			if (!this._ssId) {
				this._ssId = $.event.guid++;
			}
			$.event._ssCache[this._ssId] = new Marquee(this, o);
		});
	};
})(jQuery);