(function($){
	
	/*
	 * usage:
	 * 
	 * - initialization:
	 * 		$(document).qnTooltip(); ==> div idies: [qntooltip-hover-id-*, qntooltip-down-id-*, qntooltip-hover-class-*, qntooltip-down-class-*]
	 * 								* ==> id or class of the binded elements
	 * 
	 * - create new tooltip:
	 * 		$(document).qnTooltip('createTooltip', {id:'newTooltipId', message:"tooltipedHTML", posX: xPosition, posY: tPosition});
	 * 
	 * - open tooltip from script:
	 * 		$('#directly').click(function(e){
	 *			$(this).qnTooltip('show', {id : 'tooltipId', posX : e.pageX+20, posY : e.pageY+20});
	 *		});
	 *
	 *	enjoy :)
	 *
	 *	MK
	 */
	
	var methods = {
		init : function( options ){
		
			return this.each(function(){
				if ( $('#qnTooltip').length == 0 )
					$('body', this).append('<div id="qnTooltip"></div>');
				
				var qnTooltip = $('#qnTooltip');
				
				qnTooltip.data('tooltips', {
	            	tooltips : []
	        	});
	        	
	        	var tooltipPositions = ['position-mouse', 'position-element-lt', 'position-element-lc', 'position-element-lb',
	        					'position-element-rt', 'position-element-rc', 'position-element-rb',
	        					'position-element-ct', 'position-element-cb'];
	        	
	        	function getPosX(id, epageX, leftOffset, position, targetElement)
	        	{
	        		if(position == 'mouse')
		        		if($(window).width() > epageX+leftOffset+$('#qnTooltip-'+id).outerWidth(true))
		        			return epageX+leftOffset;
		        		else
		        			return epageX-leftOffset-$('#qnTooltip-'+id).outerWidth(true);
		        	else if(position == 'element-lt' || position == 'element-lb' || position == 'element-lc')
		        		return targetElement.offset().left - leftOffset - $('#qnTooltip-'+id).outerWidth(true);
		        	else if(position == 'element-rt' || position == 'element-rb' || position == 'element-rc')
		        		return targetElement.offset().left + targetElement.outerWidth(true) + leftOffset;
		        	else if(position == 'element-ct' || position == 'element-cb')
		        		return targetElement.offset().left + Math.round(targetElement.outerWidth(true)/2) - Math.round($('#qnTooltip-'+id).outerWidth(true)/2);
	        		
	        	};
	        	
	        	function getPosY(id, epageY, topOffset, position, targetElement)
	        	{
	        		if(position == 'mouse')
	        			if($(document).height() > epageY+topOffset+$('#qnTooltip-'+id).outerHeight(true))
	        				return epageY+topOffset;
		        		else
		        			return epageY-topOffset-$('#qnTooltip-'+id).outerHeight(true);
		        	else if(position == 'element-lt' || position == 'element-rt')
		        		return targetElement.offset().top;
		        	else if(position == 'element-lb' || position == 'element-rb')
		        		return targetElement.offset().top + targetElement.outerHeight(true) - $('#qnTooltip-'+id).outerHeight(true);
		        	else if(position == 'element-lc' || position == 'element-rc')
		        		return targetElement.offset().top + Math.round(targetElement.outerHeight(true)/2) - Math.round($('#qnTooltip-'+id).outerHeight(true)/2);
		        	else if(position == 'element-ct')
		        		return targetElement.offset().top - topOffset - $('#qnTooltip-'+id).outerHeight(true);
		        	else if(position == 'element-cb')
		        		return targetElement.offset().top + targetElement.outerHeight(true) + topOffset;
		        		
	        	};
				
				
				$('div[id^="qntooltip-hover-id-"], div[id^="qntooltip-down-id-"], div[id^="qntooltip-hover-class-"], div[id^="qntooltip-down-class-"]').each(function(){
					$(this).appendTo(qnTooltip);
					var splited = $(this).attr('id').split('-');
					var ident = splited[splited.length-1];
					var msg = $(this).html();
					var classid = (splited[2]=='id') ? '#' : '.';
					var s = $(this).attr('style');
					var c = $(this).attr('class');
					var position = 'mouse';
					
					for(p in tooltipPositions)
						if($(this).hasClass(tooltipPositions[p]))
						{
							position = tooltipPositions[p].split('position-')[1];
							break;
						}
						
					var leftOffset = $(this).css('left') == 'auto' ? 20 : parseInt($(this).css('left'));
					var topOffset = $(this).css('top') == 'auto' ? 20 : parseInt($(this).css('top'));
					
					if(splited[1]=='hover'){
						$(classid+ident).hover(function(e){
							$(document).qnTooltip('show', {id : ident, message : msg, posX : getPosX(ident, e.pageX, leftOffset, position, $(this)), posY : getPosY(ident, e.pageY, topOffset, position, $(this)), style : s, cls : c});
						},
						function(){
							$(document).qnTooltip('hide', ident);
						});
						
						$(classid+ident).mousemove(function(e){
							$(document).qnTooltip('update', {id : ident, posX : getPosX(ident, e.pageX, leftOffset, position, $(this)), posY : getPosY(ident, e.pageY, topOffset, position, $(this)), style : s, cls : c});
						});
					}
					else if(splited[1]=='down')
					{
						$(classid+ident).click(function(){
							var width = $(this).width();
							$(document).qnTooltip('show', {id : ident, message : msg, posX: getPosX(ident, position.left+width, leftOffset, position, $(this)), posY: getPosX(ident, e.pageY, topOffset, position, $(this)), style : s, cls : c});
							return false;
						});
						
						$(classid+ident).focus(function(){
							var width = $(this).width();
							$(document).qnTooltip('show', {id : ident, message : msg, posX: getPosX(ident, position.left+width, leftOffset, position, $(this)), posY: getPosX(ident, e.pageY, topOffset, position, $(this)), style : s, cls : c});
						});
						
						$(classid+ident).focusout(function(){
							$(document).qnTooltip('hide', ident);
						});
					};
					$(this).remove();
				});
			});
			
		},
		createTooltip : function(newTooltip){
			if(!$(document).qnTooltip('issetTooltip', newTooltip.id))
			{
				var tts = $('#qnTooltip').data('tooltips').tooltips;
				tts[newTooltip.id] = true;
				
				if(!newTooltip.message && $('div[id="qntooltip-hover-id-'+newTooltip.id+'"], div[id="qntooltip-down-id-'+newTooltip.id+'"]').length > 0)
					newTooltip.message = $('div[id="qntooltip-hover-id-'+newTooltip.id+'"], div[id="qntooltip-down-id-'+newTooltip.id+'"]').first().html();
				
				$('#qnTooltip').data('tooltips', {tooltips : tts}).append('<div id="qnTooltip-'+newTooltip.id+'" class="qnTooltip-element'+((newTooltip.cls && newTooltip.cls.length > 0) ? ' '+newTooltip.cls : '')+((newTooltip.style && newTooltip.style.length > 0) ? '" style="'+newTooltip.style : '')+'">'+newTooltip.message+'</div>');
			};
		},
		show : function(tooltip){
			
			if(!$(document).qnTooltip('issetTooltip', tooltip.id))
				$(document).qnTooltip('createTooltip', tooltip);
			else
				if(tooltip.message)
					$('#qnTooltip-'+tooltip.id).html(tooltip.message);
			
			if(tooltip.posX)
				$('#qnTooltip-'+tooltip.id).css('left', tooltip.posX+'px');
			if(tooltip.posY)
				$('#qnTooltip-'+tooltip.id).css('top', tooltip.posY+'px');
			
			$('#qnTooltip-'+tooltip.id).stop(true, true).fadeIn();
			
		},
		issetTooltip : function(id){
			if($('#qnTooltip').data('tooltips').tooltips[id])
				return true;
			else
				return false;
		},
		hide : function(id){
			$('#qnTooltip-'+id).stop(true, true).fadeOut();
		},
		update : function(tooltip){
			if($(document).qnTooltip('issetTooltip', tooltip.id))
			{
				var t = $('#qnTooltip-'+tooltip.id);
				if(tooltip.message)
					t.html(tooltip.message);
				if(tooltip.posX)
					t.css('left', tooltip.posX+'px');
				if(tooltip.posY)
					t.css('top', tooltip.posY+'px');
			}
		}
	};
	
	$.fn.qnTooltip = function(method) {
		if(methods[method]){
			return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
		} else if (typeof method === 'object'||!method){
			return methods.init.apply( this, arguments );
		} else {
			$.error( 'Metoda ' +  method + ' nie istnieje w jQuery.qnTooltip' );
		}
	};
})( jQuery );
