/**
 * jquery.simpletip 1.3.1. A simple tooltip plugin
 * 
 * Copyright (c) 2009 Craig Thompson
 * http://craigsworks.com
 *
 * Licensed under GPLv3
 * http://www.opensource.org/licenses/gpl-3.0.html
 *
 * Launch  : February 2009
 * Version : 1.3.1
 * Released: February 5, 2009 - 11:04am
 */
(function($) {

	function Simpletip(elem, conf) {
		var self = this;
		elem = jQuery(elem);

		var tooltip = jQuery(document.createElement('div'))
                     .addClass(conf.baseClass)
                     .addClass((conf.fixed) ? conf.fixedClass : '')
                     .addClass((conf.persistent) ? conf.persistentClass : '')
                     .html(conf.content)
                     .appendTo(elem);

		if (!conf.hidden) tooltip.show();
		else tooltip.hide();

		if (!conf.persistent) {
			elem.hover(
            function(event) { self.show(event) },
            function() { self.hide() }
         );

			if (!conf.fixed) {
				elem.mousemove(function(event) {
					if (tooltip.css('display') !== 'none') self.updatePos(event);
				});
			};
		}
		else {
			elem.click(function(event) {
				if (event.target === elem.get(0)) {
					if (tooltip.css('display') !== 'none')
						self.hide();
					else
						self.show();
				};
			});

			jQuery(window).mousedown(function(event) {
				if (tooltip.css('display') !== 'none') {
					var check = (conf.focus) ? jQuery(event.target).parents('.tooltip').andSelf().filter(function() { return this === tooltip.get(0) }).length : 0;
					if (check === 0) self.hide();
				};
			});
		};


		jQuery.extend(self,
      {
      	getVersion: function() {
      		return [1, 2, 0];
      	},

      	getParent: function() {
      		return elem;
      	},

      	getTooltip: function() {
      		return tooltip;
      	},

      	getPos: function() {
      		return tooltip.offset();
      	},

      	setPos: function(posX, posY) {
      		var elemPos = elem.offset();

      		if (typeof posX == 'string') posX = parseInt(posX) + elemPos.left;
      		if (typeof posY == 'string') posY = parseInt(posY) + elemPos.top;

      		tooltip.css({ left: posX, top: posY });

      		return self;
      	},

      	show: function(event) {
      		conf.onBeforeShow.call(self);

      		self.updatePos((conf.fixed) ? null : event);

      		switch (conf.showEffect) {
      			case 'fade':
      				tooltip.fadeIn(conf.showTime); break;
      			case 'slide':
      				tooltip.slideDown(conf.showTime, self.updatePos); break;
      			case 'custom':
      				conf.showCustom.call(tooltip, conf.showTime); break;
      			default:
      			case 'none':
      				tooltip.show(); break;
      		};

      		tooltip.addClass(conf.activeClass);

      		conf.onShow.call(self);

      		return self;
      	},

      	hide: function() {
      		conf.onBeforeHide.call(self);

      		switch (conf.hideEffect) {
      			case 'fade':
      				tooltip.fadeOut(conf.hideTime); break;
      			case 'slide':
      				tooltip.slideUp(conf.hideTime); break;
      			case 'custom':
      				conf.hideCustom.call(tooltip, conf.hideTime); break;
      			default:
      			case 'none':
      				tooltip.hide(); break;
      		};

      		tooltip.removeClass(conf.activeClass);

      		conf.onHide.call(self);

      		return self;
      	},

      	update: function(content) {
      		tooltip.html(content);
      		conf.content = content;

      		return self;
      	},

      	load: function(uri, data) {
      		conf.beforeContentLoad.call(self);

      		tooltip.load(uri, data, function() { conf.onContentLoad.call(self); });

      		return self;
      	},

      	boundryCheck: function(posX, posY) {
      		var newX = posX + tooltip.outerWidth();
      		var newY = posY + tooltip.outerHeight();

      		var windowWidth = jQuery(window).width() + jQuery(window).scrollLeft();
      		var windowHeight = jQuery(window).height() + jQuery(window).scrollTop();

      		return [(newX >= windowWidth), (newY >= windowHeight)];
      	},

      	updatePos: function(event) {
      		var tooltipWidth = tooltip.outerWidth();
      		var tooltipHeight = tooltip.outerHeight();

      		if (!event && conf.fixed) {
      			if (conf.position.constructor == Array) {
      				posX = parseInt(conf.position[0]);
      				posY = parseInt(conf.position[1]);
      			}
      			else if (jQuery(conf.position).attr('nodeType') === 1) {
      				var offset = jQuery(conf.position).offset();
      				posX = offset.left;
      				posY = offset.top;
      			}
      			else {
      				var elemPos = elem.offset();
      				var elemWidth = elem.outerWidth();
      				var elemHeight = elem.outerHeight();

      				switch (conf.position) {
      					case 'top':
      						var posX = elemPos.left - (tooltipWidth / 2) + (elemWidth / 2);
      						var posY = elemPos.top - tooltipHeight;
      						break;

      					case 'bottom':
      						var posX = elemPos.left - (tooltipWidth / 2) + (elemWidth / 2);
      						var posY = elemPos.top + elemHeight;
      						break;

      					case 'left':
      						var posX = elemPos.left - tooltipWidth;
      						var posY = elemPos.top - (tooltipHeight / 2) + (elemHeight / 2);
      						break;

      					case 'right':
      						var posX = elemPos.left + elemWidth;
      						var posY = elemPos.top - (tooltipHeight / 2) + (elemHeight / 2);
      						break;

      					default:
      					case 'default':
      						var posX = (elemWidth / 2) + elemPos.left + 20;
      						var posY = elemPos.top;
      						break;
      				};
      			};
      		}
      		else {
      			var posX = event.pageX;
      			var posY = event.pageY;
      		};

      		if (typeof conf.position != 'object') {
      			posX = posX + conf.offset[0];
      			posY = posY + conf.offset[1];

      			if (conf.boundryCheck) {
      				var overflow = self.boundryCheck(posX, posY);

      				if (overflow[0]) posX = posX - (tooltipWidth / 2) - (2 * conf.offset[0]);
      				if (overflow[1]) posY = posY - (tooltipHeight / 2) - (2 * conf.offset[1]);
      			}
      		}
      		else {
      			if (typeof conf.position[0] == "string") posX = String(posX);
      			if (typeof conf.position[1] == "string") posY = String(posY);
      		};

      		self.setPos(posX, posY);

      		return self;
      	}
      });
	};

	jQuery.fn.simpletip = function(conf) {
		// Check if a simpletip is already present
		var api = jQuery(this).eq(typeof conf == 'number' ? conf : 0).data("simpletip");
		if (api) return api;

		var relContent = jQuery(this).find('img').attr('simpletip');

		// Default configuration
		var defaultConf = {
			// Basics
			content: relContent,
			persistent: false,
			focus: false,
			hidden: true,

			// Positioning
			position: 'default',
			offset: [0, 0],
			boundryCheck: true,
			fixed: true,

			// Effects
			showEffect: 'fade',
			showTime: 150,
			showCustom: null,
			hideEffect: 'fade',
			hideTime: 150,
			hideCustom: null,

			// Selectors and classes
			baseClass: 'tooltip',
			activeClass: 'active',
			fixedClass: 'fixed',
			persistentClass: 'persistent',
			focusClass: 'focus',

			// Callbacks
			onBeforeShow: function() { },
			onShow: function() { },
			onBeforeHide: function() { },
			onHide: function() { },
			beforeContentLoad: function() { },
			onContentLoad: function() { }
		};
		jQuery.extend(defaultConf, conf);

		this.each(function() {
			var el = new Simpletip(jQuery(this), defaultConf);
			jQuery(this).data("simpletip", el);
		});

		return this;
	};
})();
