// based on http://fest07.sffs.org/js/tooltip.js
var Tooltip = Class.create();
Tooltip.prototype = {
	initialize: function (sTiplayerId, rxClassName, sXmlUrl, iOffsetTop, iOffsetLeft, bUseCursor) {
		this._tipId = sTiplayerId;
		this._rxClassName = rxClassName;
		this._sXmlUrl = sXmlUrl;
		this._iOffsetTop = iOffsetTop;
		this._iOffsetLeft = iOffsetLeft;
		this._bUseCursor = bUseCursor;

		this._cache = new Array();
		this._elem_tip = this._createToolTipBox();
		this._int_tip_id = false;
		this._last_tip = false;
		this._target = false;
		this._in_target = false;

		this._oLnks = $$('.tooltip');
		for (var i=0; i<this._oLnks.length; i++) {
			Event.observe(this._oLnks[i], 'mouseover', this._handleEvents.bindAsEventListener(this));
			Event.observe(this._oLnks[i], 'mouseout', this._handleEvents.bindAsEventListener(this));
		}
	},
	_createToolTipBox: function() {
		if(this._tipId) {	
			var tip_elem = $(this._tipId) ? $(this._tipId) : false;
			
			if(!tip_elem) {
				//tip elem not found so add to body
				var tool_tip_layer = document.createElement( 'dl' );
				tool_tip_layer.id = this._tipId;
				
				Event.observe(tool_tip_layer,'mouseover',function() {
					Element.show(tool_tip_layer);
				});
				Event.observe(tool_tip_layer,'mouseout',function() {
					Element.hide(tool_tip_layer);
				});
				tip_elem = document.body.insertBefore( tool_tip_layer, document.body.firstChild );
			}
			return tip_elem;
		}
		return false;
	},
	_handleEvents: function(event) {
		this._target = Event.element(event);
		this._int_tip_id = this.getCurrentTipId();
		
		if(event.type=='mouseover') {
			this._in_target = true;
			this.getTipContent();
		} else if(event.type=='mousemove' && this._in_target && this._cache[this._int_tip_id]!='') {
			this.positionBox();
		} else if(event.type=='mouseout') {
			this._in_target = false;
			Element.hide(this._elem_tip);
		}
	},
	getTipContent: function() {
		if(!this._cache[this._int_tip_id]) {
			var pars = 'id='+this._int_tip_id;
			var request_url = this._sXmlUrl;
			
			new Ajax.Request( request_url,{
				method: 'get',
				parameters: pars,
				onComplete:this._cacheData.bind(this)
			});
		} else { // use data cache
			this._last_tip = this._int_tip_id;
			Element.update(this._elem_tip, this._cache[this._int_tip_id]);
			this.positionBox();
		}
	},
	_cacheData: function (originalRequest) {
		//save response
		var form = originalRequest.responseXML.getElementsByTagName('form')[0];
		for (var i=0; i<form.childNodes.length; i++) {
			var node = form.childNodes[i];
			if (node.nodeType == 4) {
				this._cache[this._int_tip_id] = node.nodeValue;		
				Element.update(this._elem_tip, node.nodeValue);
				break;
			}
		}
		this._last_tip = this._int_tip_id;
		this.positionBox();
	},
	positionBox: function() {
		if (this._bUseCursor) {
			//get cursor position
			var int_x_pos = Event.pointerX(e.evnt);
			var int_y_pos = Event.pointerY(e.evnt);

			//apply user defined offset
			int_x_pos += this._iOffsetLeft;
			int_y_pos += this._iOffsetTop;
		} else {
			//get position of mouseover element
			var arr_offsets = Position.cumulativeOffset(this._target);
			var int_x_pos = arr_offsets[0] + this._target.offsetWidth + this._iOffsetLeft;
			var int_y_pos = arr_offsets[1] + this._iOffsetTop;
		}
		//keep tip within visible page area
		var tip_dimensions 	= Element.getDimensions(this._elem_tip);

		var tip_position	= new Object();	
		tip_position.x=Number(int_x_pos+tip_dimensions.width)
		tip_position.y=Number(int_y_pos+tip_dimensions.height);
		
		//if all of tip is visible then both x and y will have negative values
		var visibility = this._isVisible(tip_position);
		
		//off screen width
		if(visibility.x > 0) {
			if (!this._bUseCursor) {
				int_x_pos -= this._target.offsetWidth;
				int_x_pos -= tip_dimensions.width;
			} else {
				int_x_pos -= tip_dimensions.width;
				int_x_pos -= 2*this._iOffsetLeft;
			}
		}
		//off screen height
		if(visibility.y > 0) {
			if (!this._bUseCursor) {
				int_y_pos -= visibility.y;
			} else {
				int_y_pos -= tip_dimensions.height;
				int_y_pos -= 2*this._iOffsetTop;
			}
		}
		if(int_x_pos && int_x_pos) {	
			this._elem_tip.style.left		= int_x_pos +'px';
			this._elem_tip.style.top		= int_y_pos + 'px';

			Element.show(this._elem_tip);
		}
	},
	_isVisible: function(elem) {
		var xdiff;
		var ydiff;

		var real_area	= new Object();
		
		var viewable 	= this._viewableArea();
		var scroll_area	= this._scrollArea();
		
		real_area.x		= viewable.x+scroll_area.x;
		real_area.y		= viewable.y+scroll_area.y;

		//subtract viewport height and width from tooltip bottom and right coords
		xdiff	 = elem.x - real_area.x;
		ydiff	 = elem.y - real_area.y;
	
		return {x:xdiff,y:ydiff};
	},
	_viewableArea: function() {
		var x,y;
		if (self.innerHeight) {
			// all except Explorer
			x = self.innerWidth;
			y = self.innerHeight;
		} else if (document.documentElement && document.documentElement.clientHeight) {
			// Explorer 6 Strict Mode
			x = document.documentElement.clientWidth;
			y = document.documentElement.clientHeight;
		} else if (document.body) {
			// other Explorers
			x = document.body.clientWidth;
			y = document.body.clientHeight;
		}
		return {x:x,y:y};
	},
	_scrollArea: function() {
		var x,y;
		
		if (this.pageYOffset) {
			// all except Explorer
			x = this.pageXOffset;
			y = this.pageYOffset;
		} else if (document.documentElement && document.documentElement.scrollTop) {
			// Explorer 6 Strict
			x = document.documentElement.scrollLeft;
			y = document.documentElement.scrollTop;
		} else if (document.body) {
			// all other Explorers
			x = document.body.scrollLeft;
			y = document.body.scrollTop;
		}
		return {x:x,y:y};
	},
	getCurrentTipId: function() {
		var regex_tip_id = this._rxClassName;
		if(regex_tip_id) {
			regex_tip_id.test(this._target.className );
			var int_tip_id = (RegExp.$1 != '') ?  RegExp.$1 : false;
			return int_tip_id;
		}
		return false;
	}
}