(function($) {
	
	var defaults = {
		tooltip: true,
		headerText: null,
		markup: '<div><h4></h4><p></p></div>',
		id: 'tooltipdiv',
		contentWrapper: 'p',
		headingWrapper: 'h4',
		topClass: 'top',
		rightClass: 'right',
		bottomClass: 'bottom',
		leftClass: 'left',
		vCenterClass: 'vcenter',
		hCenterClass: 'hcenter',
		allowOverlap: false,
		position: 'top right',
		showEvent: 'mouseover',
		hideEvent: 'mouseout',
		useText:true,
		useItem:false,
		showCallback:null
	};
	
	var _settings = {};
	
	var _usetext;
	
	var _positionTooltipVertically = function(jqobj, settings, eTop, eHeight, pos) {
		switch (pos) {
			default:
			//top
			case "t":
				jqobj.css('top', eTop - parseInt(jqobj.height()));
				jqobj.removeClass(settings.vCenterClass).removeClass(settings.bottomClass).addClass(settings.topClass);
				break;
			//center
			case "c":
			case "m":	
				jqobj.css('top', (eTop + eHeight/2) - (parseInt(jqobj.height())/2));
				jqobj.removeClass(settings.topClass).removeClass(settings.bottomClass).addClass(settings.vCenterClass);
				break;
			//bottom
			case "b":
				jqobj.css('top', eTop + eHeight);
				jqobj.removeClass(settings.vCenterClass).removeClass(settings.topClass).addClass(settings.bottomClass);
				break;
		}
	};
	
	var _positionTooltipHorizontally = function(jqobj, settings, eLeft, eWidth, pos) {
		switch (pos) {
			default:
			//right
			case "r":
				jqobj.css('left', eLeft + eWidth);
				jqobj.removeClass(settings.hCenterClass).removeClass(settings.leftClass).addClass(settings.rightClass);
				break;
			//center
			case "c":
			case "m":
				jqobj.css('left', (eLeft + eWidth/2) - (parseInt(jqobj.width()/2)));
				jqobj.removeClass(settings.leftClass).removeClass(settings.rightClass).addClass(settings.hCenterClass);
				break;
			//left
			case "l":
				jqobj.css('left', eLeft - parseInt(jqobj.width()));
				jqobj.removeClass(settings.hCenterClass).removeClass(settings.rightClass).addClass(settings.leftClass);
				break;
		}
	};
	
	var _showTooltip = function() {
		if (!this._settings.tooltip && (this._usetext == null || this._usetext == '')) return;
		
		var t = $(this).offset().top;
		var l = $(this).offset().left;
		var h = parseInt($(this).height()) || parseInt($(this).css('padding-top'));
		var w = parseInt($(this).width());
		var browserWidth = (typeof(window.innerWidth) == 'number') ? window.innerWidth : document.documentElement.clientWidth;
		var browserX = (document.documentElement && document.documentElement.scrollLeft) ? document.documentElement.scrollLeft : document.body.scrollLeft;
		var browserHeight = (typeof(window.innerHeight) == 'number') ? window.innerHeight : document.documentElement.clientHeight;
		var browserY = (document.documentElement && document.documentElement.scrollTop) ? document.documentElement.scrollTop : document.body.scrollTop;
		
		if ($('body > #' + this._settings.id).length > 0) $('body > #' + this._settings.id).remove();
		
		$('body').append(this._settings.markup);
		var tt = $('body > div:last');
		tt.attr('id', this._settings.id).css({'position': 'absolute'});
		
		//header text
		if (this._settings.headerText) {
			tt.find(this._settings.headingWrapper).text(this._settings.headerText);
		} else {
			tt.find(this._settings.headingWrapper).hide();
		}
		
		//tooltip text
		if (this._settings.useText) {
			tt.find(this._settings.contentWrapper).text(this._usetext);
		} else {
			if (this._settings.useItem) {
				tt.find(this._settings.contentWrapper).html($(this).find(this._settings.useItem).html());
			} else {
				tt.find(this._settings.contentWrapper).html($(this).html());
			}
		}
		
		//get the position strings
		var pos = defaults.position.split(" ");
		if (this._settings.position.indexOf(" ") != -1) pos = this._settings.position.split(" ");
		
		//position vertically
		_positionTooltipVertically(tt, this._settings, t, h, pos[0].charAt(0).toLowerCase());
		
		var overtop = tt.get(0).offsetTop < browserY;
		var overbottom = (tt.get(0).offsetTop + parseInt(tt.height())) > (browserY + browserHeight);
		
		if (overtop && !overbottom) {
			_positionTooltipVertically(tt, this._settings, t, h, "b");
		} else if (overbottom && !overtop) {
			_positionTooltipVertically(tt, this._settings, t, h, "t");
		} else if (overtop && overbottom) {
			_positionTooltipVertically(tt, this._settings, t, h, "c");
		}
		
		//position horizontally
		_positionTooltipHorizontally(tt, this._settings, l, w, pos[1].charAt(0).toLowerCase());
		
		var overleft = tt.get(0).offsetLeft < browserX;
		var overright = (tt.get(0).offsetLeft + tt.get(0).offsetWidth) > (browserX + browserWidth);
		
		if (overright && !overleft) {
			_positionTooltipHorizontally(tt, this._settings, l, w, "l");
		} else if (overleft && !overright) {
			_positionTooltipHorizontally(tt, this._settings, l, w, "r");
		} else if (overleft && overright) {
			_positionTooltipHorizontally(tt, this._settings, l, w, "c");
		}
		
		//change position if it's overlapping the hover element
		if (!this._settings.allowOverlap && tt.is('.' + this._settings.hCenterClass) && tt.is('.' + this._settings.vCenterClass)) {
			_positionTooltipVertically(tt, this._settings, t, h, "t");
			if (tt.get(0).offsetTop < browserY) _positionTooltipVertically(tt, this._settings, t, h, "b");
		}
			
		tt.bgiframe().hide().show();
		
		if (this._settings.showCallback) {
			this._settings.showCallback({tooltip:tt, target:$(this)});
		}
		
		return false;
	};
	
	var _hideTooltip = function() {
		$('#' + this._settings.id).remove();
	};
	
	$.fn.tooltip = function(settings, text) {
		//_settings = $.extend({}, defaults, settings || {});
		
		this.each(function() {
			this._settings = $.extend({}, defaults, settings || {});
			this._usetext = (this._settings.tooltip) ? $(this).text() : text;
			
			if (this._settings.showEvent) $(this).bind(this._settings.showEvent, _showTooltip);
			if (this._settings.hideEvent) $(this).bind(this._settings.hideEvent, _hideTooltip);
		});
	};
	
})(jQuery);