var Glossary =
{
	left_pos: 50,
	right_pos: 300,
	arrow_width: 10,
	entries: {},
	visible_tooltip: null,
	xmlhttp: null,
	loading_id: null,
	link: null,
	mousex: null,
	mousey: null,
	background: null,
	use_background: false,
	
	/**
	 * Initializes this object.
	 */
	init: function()
	{
		var self = this;

		try
		{
			self.xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
		}
		catch (e1)
		{
			try
			{
				self.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
			}
			catch (e2)
			{
				self.xmlhttp = null;
			}
		}
		if (!self.xmlhttp)
		{
			if (typeof XMLHttpRequest != "undefined")
				self.xmlhttp = new XMLHttpRequest();
			else self.xmlhttp = null;
		}
	},
	
	/**
	 * Converts a style name from normal notation to camel case.
	 * The  '-' signs are removed and the following character is converted to upper case.
	 * 
	 * @param 	name		style name in normal notation
	 * @return 				style name in camel case
	 */
	style_to_camelcase: function(name)
	{
		var converted = name;
		var i = converted.indexOf('-');
		
		while (i>=0)
		{
			converted = converted.substr(0,i) +  converted.substr(i + 1,1).toUpperCase() + converted.substr(i + 2);
			i = converted.indexOf('-');
		}
		return converted;
	},

	/**
	 * Returns the computed style of an element.
	 * 
	 * @param	node		html element for that the style should be computed
	 * @param	name		name of the style property (normal notation)
	 * @return	computed style value
	 */
	get_style: function(node, name)
	{
		var style = '';

		if (node.currentStyle)
			style = node.currentStyle[this.style_to_camelcase(name)];
		else if (document.defaultView && document.defaultView.getComputedStyle)
			style = document.defaultView.getComputedStyle(node,null).getPropertyValue(name);
		return style;
	},
	
	/**
	 * Computes the absolute position of an  element.
	 * @param	node		html element
	 * @return				object with the position (contains two integer properties: "x" and "y")
	 */	
	element_position: function(node)
	{
		var op = false;
		if (window.opera)
			op = true;
		var left = node.offsetLeft - (!op && node.parentNode ? node.parentNode.scrollLeft : 0);
		var top = node.offsetTop - (!op && node.parentNode ? node.parentNode.scrollTop : 0);

		while(node.offsetParent)
		{
			node = node.offsetParent;
			left += node.offsetLeft/* + node.scrollLeft*/;
			top += node.offsetTop/* + node.scrollTop*/;
		}
		var obj = new Object;
		obj.x = left;
		obj.y = top;
		return obj;
	},
	
	/**
	 * Loads and shows the glossary entry tooltip
	 * @param	id		id of the glossary entry
	 * @param	link	calling link html element (the tooltip is shown at element's position)
	 */
	show_tooltip: function(event, id, link, use_background)
	{
		var self = Glossary;
		
		if (!event)
			event = window.event; 
		// initialize
		if (self.xmlhttp==null)
		{
			self.init();
			if (self.xmlhttp==null)
				return false;
		}
		// search for cached glossary entry
		var entry_id = 'id' + id;
		var entry = self.entries[entry_id];
		if (!entry)
		{
			// load glossary entry (not yet loaded)
			self.use_background = use_background;
			self.loading_id = id;
			self.mousex = event.clientX;
			self.mousey = event.clientY;
			self.link = link;
			var href = new String(window.location.href);
			var i = href.indexOf("#");
			if (i>=0)
				href = href.substr(0,i);
			href += (href.indexOf("?")>=0 ? "&" : "?") + "return_glossary_entry=" + id;
			self.xmlhttp.open("GET", href, true);
			self.xmlhttp.onreadystatechange = self.load_tooltip;
			self.xmlhttp.send(null);
		}
		else self.show_tooltip_internal(event.clientX, event.clientY, id, link, use_background);
		return true;
	},

	show_tooltip_internal: function(mousex, mousey, id, link, use_background)
	{
		var self = Glossary;
		var entry_id = 'id' + id;
		var entry = self.entries[entry_id];

		// hide old entry
		if (self.visible_tooltip)
			self.hide_tooltip();
		// show this entry
		if (use_background && use_background==true)
		{
			self.background = document.createElement("div");
			self.background.className = "GlossaryTooltipBackground";
			self.background.id = "GlossaryBackground";
			document.getElementsByTagName('body')[0].appendChild(self.background);
			self.background.style.width = document.body.offsetWidth + "px";
			self.background.style.height = document.body.offsetHeight + "px";
			self.background.onclick = self.hide_tooltip;
		}
		self.visible_tooltip = entry;
		var pos = self.element_position(link);
		var x_left = mousex - (self.left_pos + self.arrow_width);
		var x_right = mousex - (self.right_pos + self.arrow_width);
		var y_top = pos.y + link.offsetHeight;
		var y_bottom = pos.y + link.offsetHeight - entry.offsetHeight;
		var arrow_left = !(x_left + entry.offsetWidth>=document.body.offsetWidth);
		var winw = (window.innerWidth ? window.innerWidth : (document.documentElement.clientWidth==0 ? document.body.clientWidth : document.documentElement.clientWidth));
		var winh = (window.innerHeight ? window.innerHeight : (document.documentElement.clientHeight==0 ? document.body.clientHeight : document.documentElement.clientHeight));
		var arrow_top = !(y_top + entry.offsetHeight - document.documentElement.scrollTop>=winh);
		var new_x = (arrow_left ? x_left : x_right);
		var new_y = (arrow_top ?  y_top : y_bottom);
		
		var arrows = [entry.childNodes[1], entry.childNodes[3], entry.childNodes[14], entry.childNodes[16]];
		var arrow_borders = [entry.childNodes[0], entry.childNodes[2], entry.childNodes[13], entry.childNodes[15]];
		for (var i=0; i<arrows.length; i++)
		{
			arrows[i].style.visibility = "hidden";
			arrow_borders[i].style.visibility = "hidden";
		}
		if (arrow_left && arrow_top)
		{
			arrows[0].style.visibility = "visible";
			arrow_borders[0].style.visibility = "visible";
		}
		else if (!arrow_left && arrow_top)
		{
			arrows[1].style.visibility = "visible";
			arrow_borders[1].style.visibility = "visible";
		}
		else if (arrow_left && !arrow_top)
		{
			arrows[2].style.visibility = "visible";
			arrow_borders[2].style.visibility = "visible";
		}
		else
		{
			arrows[3].style.visibility = "visible";
			arrow_borders[3].style.visibility = "visible";
		}
		//(event.clientX - pos.x - movement)
		entry.style.left = new_x + "px";
		entry.style.top = new_y + "px";
		entry.style.visibility = "visible";
	},

	/**
	 * Hides the currently visible glossary entry tooltip
	 * @param	link	calling link html element
	 */	
	hide_tooltip: function(link)
	{
		var self = Glossary;
		if (self.visible_tooltip)
		{
			var entry = self.visible_tooltip; 
			entry.style.visibility = "hidden";
			var arrows = [entry.childNodes[1], entry.childNodes[3], entry.childNodes[14], entry.childNodes[16]];
			var arrow_borders = [entry.childNodes[0], entry.childNodes[2], entry.childNodes[13], entry.childNodes[15]];
			for (var i=0; i<arrows.length; i++)
			{
				arrows[i].style.visibility = "hidden";
				arrow_borders[i].style.visibility = "hidden";
			}
			self.visible_tooltip = null;
		}
		if (self.background)
		{
			self.background.parentNode.removeChild(self.background);
			self.background = null;
		}
		return true;
	},
	
	load_tooltip: function()
	{
		var self = Glossary;
		if (self.xmlhttp.readyState==4 && self.xmlhttp.status==200 && self.loading_id!=null)
		{
			// create entry
			var entry = document.createElement("div"); 
			var entry_inner = document.createElement("div");
			var arrow_lefttop_border = document.createElement("span");
			var arrow_lefttop = document.createElement("span");
			var arrow_righttop_border = document.createElement("span");
			var arrow_righttop = document.createElement("span");
			var arrow_leftbottom_border = document.createElement("span");
			var arrow_leftbottom = document.createElement("span");
			var arrow_rightbottom_border = document.createElement("span");
			var arrow_rightbottom = document.createElement("span");
			var b1_top = document.createElement("span");
			var b2_top = document.createElement("span");
			var b3_top = document.createElement("span");
			var b4_top = document.createElement("span");
			var b1_bottom = document.createElement("span");
			var b2_bottom = document.createElement("span");
			var b3_bottom = document.createElement("span");
			var b4_bottom = document.createElement("span");
			var entry_id = 'id' + self.loading_id;
			
			entry.appendChild(arrow_lefttop_border);
			entry.appendChild(arrow_lefttop);
			entry.appendChild(arrow_righttop_border);
			entry.appendChild(arrow_righttop);
			entry.appendChild(b1_top);
			entry.appendChild(b2_top);
			entry.appendChild(b3_top);
			entry.appendChild(b4_top);
			entry.appendChild(entry_inner);
			entry.appendChild(b4_bottom);
			entry.appendChild(b3_bottom);
			entry.appendChild(b2_bottom);
			entry.appendChild(b1_bottom);
			entry.appendChild(arrow_leftbottom_border);
			entry.appendChild(arrow_leftbottom);
			entry.appendChild(arrow_rightbottom_border);
			entry.appendChild(arrow_rightbottom);
			entry.style.position = "absolute";
			entry.style.display = "block";
			entry.style.visibility = "hidden";
			entry.className = "GlossaryTooltip";
			entry_inner.className = "GlossaryTooltip_Content";
			entry_inner.innerHTML = self.xmlhttp.responseText;
			arrow_lefttop_border.className = "GlossaryTooltip_ArrowBorder_LeftTop";
			arrow_lefttop.className = "GlossaryTooltip_Arrow_LeftTop";
			arrow_righttop_border.className = "GlossaryTooltip_ArrowBorder_RightTop";
			arrow_righttop.className = "GlossaryTooltip_Arrow_RightTop";
			arrow_leftbottom_border.className = "GlossaryTooltip_ArrowBorder_LeftBottom";
			arrow_leftbottom.className = "GlossaryTooltip_Arrow_LeftBottom";
			arrow_rightbottom_border.className = "GlossaryTooltip_ArrowBorder_RightBottom";
			arrow_rightbottom.className = "GlossaryTooltip_Arrow_RightBottom";
			arrow_lefttop_border.style.visibility = "hidden";
			arrow_lefttop.style.visibility = "hidden";
			arrow_righttop_border.style.visibility = "hidden";
			arrow_righttop.style.visibility = "hidden";
			arrow_leftbottom_border.style.visibility = "hidden";
			arrow_leftbottom.style.visibility = "hidden";
			arrow_rightbottom_border.style.visibility = "hidden";
			arrow_rightbottom.style.visibility = "hidden";
			
			b1_top.className = "GlossaryTooltip_top1";
			b2_top.className = "GlossaryTooltip_top2";
			b3_top.className = "GlossaryTooltip_top3";
			b4_top.className = "GlossaryTooltip_top4";
			b1_bottom.className = "GlossaryTooltip_bottom1";
			b2_bottom.className = "GlossaryTooltip_bottom2";
			b3_bottom.className = "GlossaryTooltip_bottom3";
			b4_bottom.className = "GlossaryTooltip_bottom4";
			
			document.getElementsByTagName('body')[0].appendChild(entry);
			self.entries[entry_id] = entry;
			self.show_tooltip_internal(self.mousex, self.mousey, self.loading_id, self.link, self.use_background);
			self.loading_id = null;
	    }
	}	
};

