var gCurrentTooltip='';		// global var for current Tooltip element (necessary for timer events)
var _mouseX=0;
var _mouseY=0;

// always observe the current mouseX and mouseY
Event.observe(document,'mousemove',function(event) {
	_mouseX=event.pointerX();
	_mouseY=event.pointerY();
});

function Tooltip(element, tooltipElement, options) {
	this.element		= $(element);
	this.tooltipElement	= $(tooltipElement);

	if(this.element && this.tooltipElement) {
		this.flagA			= false;
		this.flagB			= false;
		this.flagC			= false;
		this.tmrA;
		this.tmrB;
		this.tmrC;

		// main options
		this.property	= 'tooltip';	// property from which to read the tooltip text
		this.delayShow	= 1500;			// milliseconds to wait before displaying tooltip
		this.delayHide	= 750;			// milliseconds to wait before hiding tooltip
		this.offsetX	= 0;			// X and Y offsets of tooltipElement from mouse cursor
		this.offsetY	= 15;
		this.showEffect	= 'Appear';		// Scriptaculous Effect.xxxx
		this.showEffectOptions	= {		// Effect options
			duration: 0.5
		}
		this.hideEffect	= 'Fade';		// Scriptaculous Effect.xxxx
		this.showEffectOptions	= {		// Effect options
			duration: 0.5
		}
		this.beforeShow;				// custom event handlers
		this.afterShow;
		this.beforeHide;
		this.afterHide;

		if(options!=null) {
			if(options.property)
				this.property=options.property;
			if(options.delayShow)
				this.delayShow=options.delayShow;
			if(options.delayHide)
				this.delayHide=options.delayHide;
			if(Number(options.offsetX)>0)
				this.offsetX=Number(options.offsetX);
			if(Number(options.offsetY)>0)
				this.offsetY=Number(options.offsetY);
		}

		// set up event listeners

		this.element.tooltip=this;
		if(this.element.observe && this.tooltipElement.observe) {
			this.element.observe('mouseover', this.elementMouseOver);
			this.element.observe('mouseout', this.elementMouseOut);
			this.tooltipElement.observe('mouseover', this.tooltipElementMouseOver);
			this.tooltipElement.observe('mouseout', this.tooltipElementMouseOut);
		}
		this.tooltipElement.style.zIndex=1000;
		this.tooltipElement.style.position='absolute';
	} else {
		return false;
	}
}

Tooltip.prototype.elementMouseOver = function(event) {
	if(event.element().tooltip.flagC) {
		event.element().tooltip.flagC = false;
	} else {
		gCurrentTooltip = event.element().tooltip;
		gCurrentTooltip.flagA = true;
		gCurrentTooltip.tmrA = window.setTimeout('gCurrentTooltip.timerAComplete();',gCurrentTooltip.delayShow);
	}
}

Tooltip.prototype.elementMouseOut = function(event) {
	if(gCurrentTooltip.flagA) {
		gCurrentTooltip.flagA = false;
		window.clearTimeout(gCurrentTooltip.tmrA);
	} else {
		if(gCurrentTooltip.flagB) {
			gCurrentTooltip.tmrB = window.setTimeout('gCurrentTooltip.timerBComplete();',gCurrentTooltip.delayHide);
		} else {
			gCurrentTooltip.hideTooltip();
		}
	}
}

Tooltip.prototype.tooltipElementMouseOver = function(event) {
	gCurrentTooltip.flagC = true;
}

Tooltip.prototype.tooltipElementMouseOut = function(event) {
	gCurrentTooltip.tmrC = window.setTimeout('gCurrentTooltip.timerCComplete();',gCurrentTooltip.delayHide);
}

Tooltip.prototype.timerAComplete = function() {
	gCurrentTooltip.flagA = false;

	if(gCurrentTooltip.element.readAttribute(gCurrentTooltip.property)!=null && gCurrentTooltip.element.readAttribute(gCurrentTooltip.property) != '') {
		gCurrentTooltip.tooltipElement.innerHTML=gCurrentTooltip.element.readAttribute(gCurrentTooltip.property);
		var w=gCurrentTooltip.tooltipElement.getWidth();
		var h=gCurrentTooltip.tooltipElement.getHeight();
		var x=_mouseX+gCurrentTooltip.offsetX;
		var y=_mouseY+gCurrentTooltip.offsetY;
		if(_mouseX + w + gCurrentTooltip.offsetX > document.viewport.getWidth()) {
			x = document.viewport.getWidth() - gCurrentTooltip.offsetX - w;
		}
		if(_mouseY + h + gCurrentTooltip.offsetY > document.viewport.getHeight()) {
			y = _mouseY -  + gCurrentTooltip.offsetY - h;
		}
		x = x < 0 ? 0 : x;
		y = y < 0 ? 0 : y;
		gCurrentTooltip.tooltipElement.style.left = x + 'px';
		gCurrentTooltip.tooltipElement.style.top = y + 'px';
		gCurrentTooltip.showTooltip();
		gCurrentTooltip.flagB = true;
	}
}

Tooltip.prototype.timerBComplete = function() {
	if(!gCurrentTooltip.flagC) {
		gCurrentTooltip.hideTooltip();
		gCurrentTooltip.flagB = false;
	}
}

Tooltip.prototype.timerCComplete = function() {
	if(gCurrentTooltip.flagC) {
		gCurrentTooltip.hideTooltip();
		gCurrentTooltip.flagC = false;
	}
}

Tooltip.prototype.showTooltip = function() {
	// custom event handler
	try {
		var retVal=gCurrentTooltip.beforeShow(gCurrentTooltip);
		if(retVal===false){
			return false;
		}
	} catch(e) {}

	try {
		options='';
		if(gCurrentTooltip.showEffectOptions) {
			for(var i in gCurrentTooltip.showEffectOptions) {
				options+=i+':'+gCurrentTooltip.showEffectOptions[i]+',';
			}
			if(options.length>0) {
				options=',{'+options.substr(0,options.length-1)+'}';
			}
		}
		eval('new Effect.'+gCurrentTooltip.showEffect+'("'+gCurrentTooltip.tooltipElement.id+'"'+options+');');
	} catch(e) {
		gCurrentTooltip.tooltipElement.show();
	}

	// custom event handler
	try {
		var retVal=gCurrentTooltip.afterShow(gCurrentTooltip);
	} catch(e) {}
}

Tooltip.prototype.hideTooltip = function() {
	// custom event handler
	try {
		var retVal=gCurrentTooltip.beforeHide(gCurrentTooltip);
		if(retVal===false){
			return false;
		}
	} catch(e) {}

	try {
		options='';
		if(gCurrentTooltip.showEffectOptions) {
			for(var i in gCurrentTooltip.showEffectOptions) {
				options+=i+':'+gCurrentTooltip.showEffectOptions[i]+',';
			}
			if(options.length>0) {
				options=',{'+options.substr(0,options.length-1)+'}';
			}
		}
		eval('new Effect.'+gCurrentTooltip.hideEffect+'("'+gCurrentTooltip.tooltipElement.id+'"'+options+');');
	} catch(e) {
		gCurrentTooltip.tooltipElement.hide();
	}

	// custom event handler
	try {
		var retVal=gCurrentTooltip.afterHide(gCurrentTooltip);
	} catch(e) {}
}