(function($) {

	$.fn.ds_balloon = function(opts) {
		var timeout = false;
		var ajaxCache = {}; 
		var showing = false;
		var balloonTimeout;
		var balloonHover = false;

		var $balloon = $('<div id="' + opts.id + '" class="ds_balloon"></div>').
			appendTo('body').
			hide().
			css({
				position: 'absolute',
				width: opts.width,
				zIndex: 999999999
			}).
			mouseover(function(e) {	balloonHover = true; }).
			mouseout(function(e) { balloonHover = false; });

		var $wait = $('<img src="http://static.dailystrength.org/templates/images/wait.gif" />');

		var getSourceURL = function(el) {

			var classes = $(el).attr('class').split(' ');
			var so, sur, surface, so_class, so_id;
			$.each(classes, function(i,v) {
				if (v.match(/^so-/)) { 
					so = classes[i].split('-');
					so_class = so[1];
					so_id = so[2];
				} else if (v.match(/^sur-/)) {
					sur = classes[i].split('-');
					surface = sur[1];
				}
			});

			return '/_ext/Surface?pop=y' +
				'&class=' + so_class +
				'&id=' + so_id + 
				'&surface=' + surface
		};

		var showBalloon = function(e,$this,url) {
			balloonTimeout = setTimeout(function() {
				$balloon.appendTo($this);
				if (!timeout) {
					positionBalloon(e,$this); 

					$balloon.empty().show();

					if (!ajaxCache[url]) {
						$wait.clone().appendTo($balloon);
						$balloon.load(
							url,
							'',
							function(text) {
								ajaxCache[url] = text;
							}
						);	
					} else {
						$balloon.html(ajaxCache[url]);
					}
				}
				timeout = true;
			}, 300);
		}

		var hideBalloon = function() {
			$balloon.hide();
			timeout = false;
			clearTimeout(balloonTimeout);
			balloonTimeout = false;
			balloonHover = false;
		}

		var positionBalloon = function(e,$this) {
			var $container = $this.parent().parent();
			var el_offset = $this.offset();
            var x_origin =  $container.offset().left;
			var balloon_width = $balloon.width();
	
			var balloon_top =  $this.offset().top - $container.parent().parent().offset().top + opts.topOffset;
			var balloon_left = el_offset.left + opts.leftOffset - x_origin;


            if( x_origin + balloon_left+balloon_width > x_origin + $container.width())  {
                 balloon_left =  el_offset.left - $this.width() - x_origin - balloon_width + opts.leftOffset +16;    
            }

			$balloon.css({
				top: balloon_top,
				left: balloon_left
			});
		}

		var over = function(e) {
			if (!showing) {
				showing = true;
				var $this = $(this);
				var url = getSourceURL($this)
				showBalloon(e,$this,url); 
			}
		};

		var out = function(e) {
			if (showing) {
				var $this = $(this);
				hideBalloon();
				balloonHoverTimeout = false;
				showing = false;
			}
		};

		return $(this).each(function() {
			var $this = $(this);
			$this.hover(over,out);
		});
	};

})(jQuery);
