/**
 * @author mats
 */
function Tooltip(opener, tooltip, options) {
	this.opener = $(opener);
	this.tooltip = $(tooltip).remove();
	$(document.getElementsByTagName("body")[0]).insert(this.tooltip);
	this.tooltip.hide();
	this.options = options;
	this.tooltip._style = {};
	
	this.hideTimer = null;
	this.showTimer = null;
	
	this.setOptions(options);
	this.events();
	this.position();
	if (this.options.ajax) {
		this.href = this.tooltip.innerHTML.strip();
	}
}

Tooltip.prototype = {
	events: function() {
		this.opener.observe("mouseover", this.open.bind(this));
		this.opener.observe("mouseout", this.close.bind(this));
		this.tooltip.observe("mouseover", this.dontCloseTooltip.bind(this));
		this.tooltip.observe("mouseout", this.close.bind(this));
	},
	
	positionInViewport: function(x, y, tooltipSize) {
		var viewportWidth = document.viewport.getWidth();
		var tooltipWidth = tooltipSize.width;
		var left = Math.min(x + this.options.howBigIsTheCursor.width, (viewportWidth - tooltipWidth) - this.options.howWideIsTheScrollBar );
		return {
			left: Math.max(left, 0) + "px",
			top: Math.max(parseInt(y + this.options.howBigIsTheCursor.height, 10), 0) + "px"
		};
	},
	
	position: function(event) {
		var pos = this.opener.cumulativeOffset();
		var osize = this.opener.getDimensions();
		var tsize = this.tooltip.getDimensions();
		if (this.options.positionRelativeTo === 'mouse' && typeof(event) !== "undefined") {
			var screenX = event.pageX, screenY = event.pageY;
			this.tooltip._style = this.positionInViewport(screenX, screenY, tsize);
		}
		else if (this.options.positionRelativeTo === 'over') {
			this.tooltip._style = {
				left: parseInt(pos.left, 10) + "px",
				top: parseInt(pos.top, 10) + "px"
			};
		}
		else { //this.options.positionRelativeTo === 'element'
			if (this.options.position === "right") {
				this.tooltip._style = {
					left: parseInt(pos.left - (tsize.width - osize.width) - this.options.negativeLeftOffset, 10) + "px",
					top: parseInt(pos.top + osize.height + this.options.topOffset, 10) + "px"
				};
			}
			else {
				this.tooltip._style = {
					left: parseInt(pos.left, 10) + "px",
					top: parseInt(pos.top + osize.height, 10) + "px"
				};
			}
		}
		this.tooltip.setStyle(this.tooltip._style);
	},
	
	open: function(event) {
		event.stop();
		if (this.hideTimer !== null) {
			clearTimeout(this.hideTimer);
		}
		this.showTimer = setTimeout(function() {
			if (this.options.useEffects) {
				this.effectOpen(event);
			}
			else {
				if (this.options.positionRelativeTo === 'mouse') {
					this.position(event);
				}
				this.options.beforeShow();
				this.tooltip.show();
				this.options.afterShow();
			}
		}.bind(this), this.options.showTimeout);
	},
	
	dontCloseTooltip:function(event) {
		event.stop();
		if (this.hideTimer !== null) {
			clearTimeout(this.hideTimer);
		}
		if (this.showTimer !== null) {
			clearTimeout(this.showTimer);
		}
	},
	
	close: function(event) {
		event.stop();
		if (this.showTimer !== null) {
			clearTimeout(this.showTimer);
		}
		this.hideTimer = setTimeout(function() {
			if (this.options.useEffects) {
				this.effectClose();
			}
			else {
				this.options.beforeHide();
				this.tooltip.hide();
				this.options.afterHide();
			}
		}.bind(this), this.options.hideTimeout);
	},
	
	effectOpen: function(event) {
		if (this.options.positionRelativeTo === 'mouse') {
			this.position(event);
		}
		new Effect.Appear(this.tooltip, {
			duration:0.3,
			beforeStart:this.options.beforeShow.bind(this),
			afterFinish:this.options.afterShow.bind(this)
		});
	},
	
	effectClose: function() {
		new Effect.Fade(this.tooltip, {
			duration:0.3,
			beforeStart:this.options.beforeHide.bind(this),
			afterFinish:this.options.afterHide.bind(this)
		});
	},
	
	setOptions: function(options) {
		this.options = {
			showTimeout:			250, // the delay before the menu closes
			hideTimeout:			0,
			width:					200,
			beforeShow:				Prototype.emptyFunction,
			afterShow:				Prototype.emptyFunction,
			beforeHide:				Prototype.emptyFunction,
			afterHide:				Prototype.emptyFunction,
			leftOffset:				0,
			topOffset:				0,
			negativeLeftOffset:		0,
			negativeTopOffset:		0,
			useEffects:				false,
			zIndex:					5000,
			ajax:					false,
			ajaxContentLoaded:		false,
			positionRelativeTo:		'element', // 'mouse', 'over'
			position:				'left', // 'left', 'right'
			howBigIsTheCursor:		{
				height:8,
				width:8
			},
			howWideIsTheScrollBar:	42
		};
		Object.extend(this.options, options || {});
		this.options.beforeShow = this.options.beforeShow.bind(this);
		this.options.afterShow = this.options.afterShow.bind(this);
		this.options.beforeHide = this.options.beforeHide.bind(this);
		this.options.afterHide = this.options.afterHide.bind(this);
	}
};
