(function($) {
	$.fn.mTooltip = function(o)
	{
		o = $.extend({
			// Predkosc animacji
			showSpeed: '',
			hideSpeed: '',
			// Opoznienia
			showDelay: 100,
			hideDelay: 500,
			checkDelay: 50,
			// Tooltip
			opacity: 0.8,
			top: 0,
			left: 0,
			// Lokalne
			box: null,
			src: null,
			showTimeoutId: null,
			hideTimeoutId: null
		}, o);
		// Timeouty
		function _clearTimeouts()
		{
			clearTimeout(o.showTimeoutId);
			clearTimeout(o.hideTimeoutId);
		}
		// Utworzenie obiektu tooltipa
		function _create()
		{
			_clearTimeouts();

			if (o.box) {
				o.box.fadeOut(o.hideSpeed);
				o.box = null;
			}
			o.box = $(o.src).appendTo("body");
			o.box.css({"position": "absolute", "zIndex": "9999", "cursor": "help", 'opacity': o.opacity});

			// Delay to show.
			o.showTimeoutId = setTimeout(function() {
				o.box.fadeIn(o.showSpeed);
			}, o.showDelay);
		}
		// Ukrywanie tooltipa
		function _hide()
		{
			o.hideTimeoutId = setTimeout(function() {
				if (o.box) {
					o.box.fadeOut(o.hideSpeed);
				}
				o.box = null;
			}, o.hideDelay);
		}
		// Pelny wymiar boxu
		function _outerSize(e, name)
		{
			var size = name == 'height' ? e.height() : e.width();

			var padd = name == 'height' ? 'top' : 'left',  // top or left
		    	bord = name == 'height' ? 'bottom' : 'right'; // bottom or right

		    size = size + _toInt(e.css('padding-' + padd)) + _toInt(e.css('padding-' + bord)) + _toInt(e.css('border-' + padd + '-width')) + _toInt(e.css('border-' + bord + '-width'));

		    return size;
		}
		// Int
		function _toInt(v)
		{
			return parseInt(v, 10) || 0;
		}
		// Ustawianie pozycji tooltipa
		function _setPos(lm, tm)
		{
			if (o.box) {
				// Wysokosc boxa
				var _bH = _outerSize(o.box, 'height');
				// Szerokosc boxa
				var _bW = _outerSize(o.box, 'width');
				// Viewport width
				var _vpW = $(window).width();
				// Viewport height
				var _vpH = (window.pageYOffset || document.documentElement.scrollTop) + (self.innerHeight || $.boxModel && document.documentElement.clientHeight || document.body.clientHeight) - 20;

				var _pX = lm;
				var _pY = tm;

				o.left = (o.left || 4);
				o.top = (o.top || 4);
				//console.log("_bH %i _bW %i _vpW %i _vpH %i lm %i tm %i", _bH, _bW, _vpW, _vpH, lm, tm);

				// Szerokosc, left
				if (_pX + _bW + o.left > _vpW) {
					//console.log('1. _pX %i', _pX);
					_pX = _pX - _bW - o.left;
				} else {
					//console.log('1b. _pX %i', _pX);
					_pX = _pX + o.left;
				}
				// Wysokosc, top
				if (_pY + _bH + o.top > _vpH) {
					//console.log('2. _pY %i', _pY);
					_pY = _pY - _bH - o.top;
				} else {
					//console.log('2b. _pY %i', _pY);
					_pY = _pY + o.top;
				}
				o.box.css({
					top: _pY,
					left: _pX
				});
			} else {
				setTimeout(function() {
					_setPos(lm, tm);
				}, o.checkDelay);
			}
		}
		return this.each(function()
		{
			var self = $(this);
			// Ustawianie eventow na elemencie
			self
				.mouseover(function()
				{
					o.src = self.attr('href');
					self.attr('title', '');
					_create();
				})
				.mouseout(function()
				{
					_hide();
				})
				.mousemove(function(e)
				{
					_setPos(e.pageX, e.pageY);
				})
				.focus(function(e)
				{
					self.trigger('mouseover');

					_setPos(e.pageX, e.pageY);
				})
				.blur(function()
				{
					self.trigger('mouseout');
				})
		});
	};
}(jQuery));
