/**
 * @author alexander.farkas
 */
(function($){
	$.ui = $.ui ||
    {};
	var toolTipClass = 'tooltip'+new Date().getTime();
	$.fn.extend({
        tooltip: function(options){
            var args = Array.prototype.slice.call(arguments, 1);
            return this.each(function(){
                if (typeof options == "string") {
                    var tooltip = $.data(this, "ui-tooltip");
                    tooltip[options].apply(tooltip, args);
                }
                else 
                    if (!$.data(this, "ui-tooltip")) {
                        $.data(this, "ui-tooltip", new $.ui.Tooltip(this, options));
                    }
            });
        }
    });
	$.ui.Tooltip = function(elm, o){
		this.o = $.extend({
			contentFrom: 'link',
			contentWrapper: '<div></div>',
			showEvents: ['mouseenter', 'focus'],
			hideEvents: ['mouseleave', 'blur'],
			extraClass: 'tooltip',
			rePos: true,
			posHorizontal: 'center',
			posVertical: 'top',
			topCorrect: 0,
			leftCorrect: 0,
			showAnim: false,
			showAnimOp: false,
			hideAnim: false,
			hideAnimOp: false
		}, o);
		var that = this,
		id = 'tooltip'+ new Date().getTime();
		
		this.elm = $(elm).attr({'tabindex': 0, 'aria-haspopup': 'true'});
		
		switch (this.o.contentFrom) {
		  case "title":
		    this.tip = $(this.o.contentWrapper).html(this.elm.attr('title')).attr({'id': id});
			this.elm.attr({'title': ''});
		    break;
		  case "link":
		    this.tip = $(this.elm.attr('href'));
			if(!this.tip.is('.'+toolTipClass) && this.o.rePos){
				this.tip = this.tip.clone();
				this.tip.end().remove();
			}
		    break;
		  default:
			if(typeof this.o.contentFrom == 'object'){
				this.tip = this.o.contentFrom;
			} else {
				this.tip = $(this.o.contentWrapper).html(this.o.contentFrom).attr({'id': id});
			}
		    break;
		}
		if (!this.tip.is('.' + toolTipClass)) {
			this.tip.css({
				display: 'none'
			}).addClass(this.o.extraClass).attr({
				'aria-hidden': true
			}).attr({
				'role': 'tooltip'
			});
			if(this.o.rePos){
				this.tip.appendTo('body');
			}
		}
		this.timer = null;
		this.elm.attr({'role': 'describedby-'+this.tip.attr('id')}).attr({
				'aria-describedby': this.tip.attr('id')
			});
		var show = function(e){
			that.show.call(that, e);
		},
		hide = function(){
			that.timer = setTimeout(function(){
				that.hide.call(that);
			}, 9);
		};
		$.each(this.o.showEvents, function(i, ev){
			that.elm.bind(ev, show);
			that.tip.bind(ev, show);
			
		});
		$.each(this.o.hideEvents, function(i, ev){
			that.elm.bind(ev, hide);
			if (!that.tip.is('.' + toolTipClass)) {
				that.tip.bind(ev, hide);
			}
		});
		this.tip.addClass(toolTipClass);
	};
	$.extend($.ui.Tooltip.prototype, {
		calcPos: function(intPos, o){
			o = o || this.o;
			var nPos = {},
			tipHeight = this.tip.outerHeight(), 
			tipWidth = this.tip.outerWidth(),
			subLeft = 0,
			subTop = 0;
			nPos.top = intPos.top;
			nPos.left = intPos.left;
			if(o.posHorizontal == 'center'){
				subLeft = tipWidth / 2;
				nPos.left = intPos.left - subLeft;
			} else if (o.posHorizontal == 'right'){
				subLeft = tipWidth;
				nPos.left = intPos.left - subLeft;
			}
			if(this.o.posVertical == 'middle'){
				subTop = tipHeight / 2;
				nPos.top = intPos.top - subTop;
			} else if (o.posVertical == 'top'){
				subTop = tipHeight;
				nPos.top = intPos.top - subTop;
			}
			if($(window).scrollTop() > nPos.top){
				nPos.top = $(window).scrollTop()+5;
			} else if($(window).scrollTop() + $(window).height() < nPos.top + tipHeight){
				nPos.top = $(window).scrollTop() + $(window).height() - tipHeight - 10;
			}
			if($(window).scrollLeft() > nPos.left){
				nPos.left = $(window).scrollLeft()+5;
			} else if($(window).width() + $(window).scrollLeft() < nPos.left + tipWidth){
				nPos.left = $(window).width() + $(window).scrollLeft() - tipWidth - 10;
			}
			return nPos;
		},
		show: function(e){
			clearInterval(this.timer);
			if(this.tip.is(':hidden')){
				var intPos = {},
				o = this.o,
				nPos;
				if(this.o.rePos){
					if(isFinite(e.pageX)){
						intPos.top =  e.pageY;
						intPos.left = e.pageX;
					} else {
						intPos = this.elm.offset();
					}
					intPos.top = intPos.top + o.topCorrect;
					intPos.left = intPos.left + o.leftCorrect;
					nPos = this.calcPos(intPos);
					this.tip.css(nPos);
				}
				this.tip.attr({'aria-hidden': false});
				if(o.showAnim){
					this.tip[o.showAnim](o.showAnimOp);
				} else {
					this.tip.css({display: 'block'});
				}
				
			}
		},
		hide: function(){
			var o = this.o;
			this.tip.attr({'aria-hidden': true});
			if(o.hideAnim){
				this.tip[o.hideAnim](o.hideAnimOp);
			} else {
				this.tip.css({display: 'none'});
			}
		}
	});
})(jQuery);
