(function($) {
	function _bubble() {
		this.options = {
			speed : "fast",
			url : undefined,
			refresh : true,
			callback : undefined
		};
		this.wrap = undefined;
		this.event = undefined;
		this.removable = true;
		this.on_duty = false;
		this.make_bubble = function(event) {
			var wrap = $("<div>").addClass('Bubble').css( {
				position : 'absolute',
				display : 'none',
				width : '241px',
				background : 'url(/img/bubble_bottom.png) no-repeat bottom center',
				margin : 0,
				padding : '0 0 31px 0'
			});

			var top = $("<div>").addClass('BubbleTop').css( {
				width : '241px',
				background : 'url(/img/bubble_top.png) no-repeat top center',
				margin : 0,
				padding : '16px 0 0 0'
			});

			var mid = $("<div>").addClass('BubbleMid').css( {
				width : '209px',
				background : 'url(/img/bubble_mid.png) repeat-y center center',
				margin : 0,
				padding : '0 16px'
			});

			var content = $("<div>").addClass('BubbleContent').css( {
				margin : '0 6px 0 0',
				padding : 0,
				fontSize : '90%',
				border : '1px solid #fff'
			});

			var clear = $("<div>").css( {
				display : 'block',
				height : 0,
				clear : 'both',
				visibility : 'hidden',
				lineHeight : '1px',
				height : '1px'
			});

			var close = $("<span>cerrar </span>").addClass('BubbleClose').css( {
				position : 'absolute',
				cursor : 'pointer',
				fontSize : '75%',
				color : '#92bec3',
				margin : 0,
				padding : 0,
				top : '4px',
				right : '12px'
			});
			var img_close = $("<img>").attr('src', '/img/icon_close.gif').attr('alt',
					'cerrar').attr('title', 'cerrar').css( {});
			var t = this;
			close.append(img_close).click(function() {
				t.wrap.slideUp(t.options.speed, function() {
					$(this).remove();
				});
				$("body").unbind('click');
			});
			content
					.append("<span><img src='/img/ajax_loader.gif'/>Loading...</span>");
			mid.append(content).append(clear);
			wrap.append(top.append(mid));
			wrap.append(close);
			$("body").prepend(wrap);
			return wrap;
		};

		this.show = function() {
			var event = this.event;
			var height = this.wrap.height();
			var y = event.pageY - height - 40;
			var x = event.pageX - 100;
			y = (y < 10 ? 10 : y);
			var body_width = $("body").width();
			x = (x > body_width - 251 ? body_width - 251 : x);
			x = (x < 0 ? 0 : x);
			this.wrap.css( {
				zIndex : 100,
				top : y + "px",
				left : x + "px"
			});
			if (this.wrap.not(":visible")) {
				this.wrap.slideDown(this.options.speed);
			}
		};

		this.reload = function(options) {
			var t = this;
			this.wrap.find('.BubbleContent').load(options.url, function() {
				t.success();
			});
		};

		this.success = function() {
			if (this.options.callback !== undefined) {
				// this.options.callback(this);
				this.options.callback = this;
			}
			var t = this;
			$(".BubbleContent").livequery(function() {
				$(this).find("form").ajaxForm( {
					type : 'post',
					target : t.wrap.find(".BubbleContent"),
					success : function(data) {
						if (t.wrap.find(".BubbleContent form").size()) {
							t.success();
						} else {
							if (t.options.refresh) {
								setTimeout("window.location.reload()", 1000);
							} else {
								t.success();
							}
						}
					}
				});
			}, function() {
				;
			});
			this.wrap.find(".DoClose").css( {
				cursor : 'pointer'
			}).click(function() {
				t.wrap.slideUp(t.options.speed, function() {
					$(this).remove();
				});
				$("body").unbind('click');
				target: t.wrap.find(".BubbleContent").html("");
			});
			this.wrap.hover(function() {
				t.removable = false;
			}, function() {
				t.removable = true;
			});
			$("body").mousedown(function() {
				if (t.removable && !t.on_duty) {
					t.wrap.slideUp(t.options.speed, function() {
						$(this).remove();
						t.on_duty = false;
					});
					$(this).unbind('mousedown');
				}
			});
			this.show();
		};

	}
	;

	$.fn.bubble = function(action, options) {
		var $t = $(this);
		var _o = new _bubble();
		_o.options = $.extend(_o.options, options || {});
		switch (action) {
		case 'click':
			$t.click(function(event) {
				if (_o.wrap !== undefined && _o.wrap.is(':visible')) {
					return;
				}
				_o.wrap = _o.make_bubble(event);
				_o.event = event;
				makeHttpRequest(_o.options.url, updateContent, _o, $t, $(this));
				// _o.wrap.find('.BubbleContent').load(_o.options.url,function(){_o.success();});
				});
			break;
		default:
			;
		}
	};

	function updateContent(response, _o, $t, $this) {
		// alert(response.toString());
		_o.wrap.find('.BubbleContent').html(response.toString());
		_o.success();
		response = "";
		_o = new _bubble();

	}

	function makeHttpRequest(url, callback_function, _o, $t, $this, return_xml) {

		// alert(url);
		var http_request, response, i;
		response = "";

		var activex_ids = [ 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP',
				'Microsoft.XMLHTTP' ];

		if (window.XMLHttpRequest) { // Mozilla, Safari, IE7+...
			http_request = new XMLHttpRequest();
			if (http_request.overrideMimeType) {
				http_request.overrideMimeType('text/xml');
			}
		} else if (window.ActiveXObject) { // IE6 and older
			for (i = 0; i < activex_ids.length; i++) {
				try {
					http_request = new ActiveXObject(activex_ids[i]);
				} catch (e) {
				}
			}
		}

		if (!http_request) {
			alert("Unfortunately your browser doesn't support this feature.");
			return false;
		}

		http_request.onreadystatechange = function() {
			if (http_request.readyState !== 4) {
				// not ready yet
				return;
			}
			if (http_request.status !== 200) {
				// ready, but not OK
				alert('There was a problem with the request.(Code: ' + http_request.status + ')');
				return;
			}
			if (return_xml) {
				response = http_request.responseXML;
			} else {
				response = http_request.responseText;
			}
			// invoke the callback
			callback_function(response, _o, $t, $this);

			// return response;
		};

		http_request.open('GET', url, true);
		http_request.send(null);
	}

})(jQuery);