var lastGeneratedId = 0;
var tooltips = new Array();

/*class defintion of call*/
function TooltipText( id, title, dispatcher ) {
	if( id ) {
		this.id = id;
	}
	else {
		this.id = 'tooltip' + ( ++lastGeneratedId );
	}
	
	this.mouseIsOver = false;
	
	this.dispatcher = dispatcher;
	
	this.title = title;
	
	var container = document.createElement( 'div' );
	
	container.className = 'tooltipText';
	container.style.display = 'inline';
	container.style.visibility = 'hidden';
	
	document.body.appendChild( container );
	
	this.container = container;
	
	container.innerHTML = title; /*there 2 types regular and advanced tooltip */
	
	this.setPosition();
	
	// Set a reference to the Javascript object
	container.TooltipText = {
		'object' : this
	}
	
	container.onmouseover = function() {
		var object = this.TooltipText.object;
		
		if( object ) {
			object.mouseIsOver = true;
		}
	}
	
	container.onmouseout = function() {
		var object = this.TooltipText.object;
		
		
		if( object ) {
			object.mouseIsOver = false;
			
			if( object.timerId ) {
				clearTimeout( object.timerId );
			}
			
			if( object.container.style.visibility != 'hidden' ) {
				object.timerId = setTimeout( 'window.tooltips["' + object.id + '"].hide();', 500 );
			}
		}
	}
	
	container.onclick = function() {
		var object = this.TooltipText.object;
		
		if( object ) {
			object.mouseIsOver = false;
			
			object.hide( true );
		}
	}
	
	// Dispatcher
	dispatcher.onmouseover = function( event ) {
		var object = this.TooltipText.object;
		
		if( object ) {
			if( object.timerId ) {
				clearTimeout( object.timerId );
			}
			
			if( object.container.style.visibility == 'hidden' ) {
				object.timerId = setTimeout( 'window.tooltips["' + object.id + '"].show();', 250 );
			}
		}
	}
	
	dispatcher.onmouseout = function() {
		var object = this.TooltipText.object;
		
		if( object ) {
			if( object.timerId ) {
				clearTimeout( object.timerId );
			}
			
			if( object.container.style.visibility != 'hidden' ) {
				object.timerId = setTimeout( 'window.tooltips["' + object.id + '"].hide();', 500 );
			}
		}
	}
	
	dispatcher.TooltipText = {
		'object' : this
	}
	
	window.tooltips[this.id] = this;
	
	return this;
}

TooltipText.prototype.destroy = function() {
	this.dispatcher.TooltipText = null;
	this.dispatcher.onmouseover = null;
	this.dispatcher.onmouseout = null;
	document.body.removeChild( this.container );
	window.tooltips[this.id] = null;
}

TooltipText.prototype.show = function() {
	// Before showing, we hide the other tooltips
	for( key in window.tooltips ) {
		window.tooltips[key].hide();
	}
	
	// Now we show the current tooltip
	//this.container.style.display = 'inline';
	//alert(this.container.style.right);
	this.container.style.visibility = 'visible';
}

TooltipText.prototype.hide = function( force ) {
	if( !this.mouseIsOver || force === true ) {
		this.container.style.visibility = 'hidden';
	}
}

TooltipText.prototype.setPosition = function() {
	var container = this.container;
	
	if( container ) {
		container.style.position = 'absolute';
		
		var pos = getAbsolutePosition( this.dispatcher );
		
		if( getCurrentStyle( this.dispatcher, 'direction' ) == 'ltr' ) {
			container.style.left = pos.left + 'px';
		}
		else {
			container.style.right = pos.right + 'px';
		}

		// Check if the ACRONYM object is on the bottom
		// margin of the screen...
		var y, h;
		
		if( window.innerHeight ) {
			y = window.pageYOffset;
			h = window.innerHeight;
		}
		else if( document.documentElement && document.documentElement.scrollTop ) {
			y = document.documentElement.scrollTop;
			h = document.documentElement.clientHeight;
		}
		else if( document.body ) {
			y = document.body.scrollTop;
			h = document.body.clientHeight;
		}
		
		if( pos.bottom + container.offsetHeight > y + h ) {
			container.style.top = ( pos.top - container.offsetHeight ) + 'px';
		}
		else {
			container.style.top = ( pos.top + this.dispatcher.offsetHeight ) + 'px';
		}
		
		return true;
	}
	
	return false;
}

function AdvancedAcronym( acronymObject ) {
	if( acronymObject ) {
		var tooltipId = null;
		
		if( acronymObject.id ) {
			tooltipId = acronymObject.id + 'tooltip';
		}
		
		var title;
		
		title = acronymObject.getAttribute( 'html' );
		
		if( !title ) {
			title = acronymObject.getAttribute( 'title' );
		}
		
		if( !title ) {
			title = '';
		}
		
		var tooltip = new TooltipText( tooltipId, title, acronymObject );
		
		this.tooltip = tooltip;
		
		acronymObject.setAttribute( 'title', '' );
	}
	
	return this;
}

function initializeTooltips() {
	// TODO: what to do if the function
	// is called two times?
	// Maybe use the method in TooltipText.destroy() ...
	
	var acronyms = document.getElementsByTagName( 'acronym' );
	
	for( var i = 0; i < acronyms.length; i++ ) {
		AdvancedAcronym( acronyms[i] );
	}
	
	// If the window is resized, we need to reposition
	// all the tooltips.
	AddEventListener( window, 'resize', repositionTooltips, false );
	AddEventListener( window, 'scroll', repositionTooltips, false );
}

function AddEventListener( object, eventName, handler, bubbling ) {
	var onEventName = 'on' + eventName;
	
	if( object.addEventListener ) {
		// DOM standard
		object.addEventListener( eventName, handler, bubbling );
	}
	else if( object.attachEvent ) {
		// Internet Explorer
		var r = object.attachEvent( onEventName, handler );
	}
	else if( object[onEventName] != null ) {
		// Older browsers
		var oldHandler = object[onEventName];
		
		object[onEventName] = function() {
			handler();
			oldHandler();
		}
	}
	else {
		object[onEventName] = handler;
	}
}

function repositionTooltips() {
	var key;
	
	for( key in window.tooltips ) {
		window.tooltips[key].setPosition();
	}
}

/* COMMON FUNCTIONS */
/* TODO: Move? */

function getAbsoluteLeft(objectId) {
	// Get an object left position from the upper left viewport corner
	// Tested with relative and nested objects
	//o = document.getElementById(objectId)
	o = objectId;
	oLeft = o.offsetLeft            // Get left position from the parent object
	while(o.offsetParent!=null) {   // Parse the parent hierarchy up to the document element
		oParent = o.offsetParent    // Get parent object reference
		oLeft += oParent.offsetLeft // Add parent left position
		o = oParent
	}
	// Return left postion
	return oLeft
}

function getAbsoluteTop(objectId) {
	// Get an object top position from the upper left viewport corner
	// Tested with relative and nested objects
	//o = document.getElementById(objectId)
	o = objectId;
	oTop = o.offsetTop            // Get top position from the parent object
	while(o.offsetParent!=null) { // Parse the parent hierarchy up to the document element
		oParent = o.offsetParent  // Get parent object reference
		oTop += oParent.offsetTop // Add parent top position
		o = oParent
	}
	// Return top position
	return oTop
}

function getAbsolutePosition(objectId) {
	o = objectId;
	var oTop = o.offsetTop;
	var oLeft = o.offsetLeft;
	
	var oWidth = o.offsetWidth;
	var oHeight = o.offsetHeight;
	
	while(o.offsetParent!=null) {
		oParent = o.offsetParent;
		oTop += oParent.offsetTop;
		oLeft += oParent.offsetLeft;
		
		o = oParent;
	}
	
	oRight = document.body.clientWidth - ( oLeft + oWidth );
	oBottom = document.body.clientHeight - ( oTop + oHeight );
	
	return {
		'top' : oTop,
		'left' : oLeft,
		'right' : oRight,
		'bottom' : oBottom
	}
}

function getCurrentStyle( object, property ) {
	if( object.currentStyle )
		return object.currentStyle[property];

	if( window.getComputedStyle )
		return window.getComputedStyle( object, null ).getPropertyValue( property );

	return null;
}