// ================================================================================================
// Hover
// ------------------------------------------------------------------------------------------------

var Hover = {
	shim: null,
	shimNeeded: true,
	activeElement: null,
	mouse: { x: 0, y: 0, lastX: 0, lastY: 0 },
	mouseObserver: null,
	elements: $H(),
	
	init: function() {
		if (!this.shimNeeded || this.shim != null)
			return;
		var agent = navigator.userAgent.toLowerCase();
		this.shimNeeded = agent.indexOf("msie") != -1 && agent.indexOf("msie 7.") == -1 && agent.indexOf("opera") == -1;
		if (!this.shimNeeded)
			return;
		this.shim = $(document.createElement("iframe"));
		this.shim.src = "javascript:void(0)";
		this.shim.setAttribute("scrolling", "no");
		this.shim.setAttribute("frameborder", "0");
		this.shim.style.position = "absolute";
		this.shim.style.zIndex = 1001;
		this.shim.style.filter = "progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)";
		this.shim.hide();
		document.body.appendChild(this.shim);
	},
	
	prepare: function(id, originatingObject, width) {
		var el = new HoverElement(id, originatingObject, width);
		this.elements[id] = el;
		document.body.appendChild(el.container);
		el.container.hide();
		return el;
	},

	remove: function(element) {
		this.elements[element.id] = null;
		document.body.removeChild(element.container);
	},
	
	prepareTooltip: function() {
		var el = new Tooltip();
		this.elements[el.id] = el;
		document.body.appendChild(el.container);
		return el;
	},
	
	showTooltip: function(msg, event) {
		this.hide(); // Hide any previous element..
		this.mouseObserver = this.move.bindAsEventListener(this);
		Event.observe(document, "mousemove", this.mouseObserver);
		this.id = "tooltip";
		var cachedElement = this.elements[this.id];
		var el = this.activeElement = (cachedElement ? cachedElement : this.prepareTooltip());
		el.originatingObject = Event.element(event);
		el.setContent(msg);
		this.move(event);
		el.show();
	},
	
	showMarkup: function(id, markup, event, width) {
		this.hide(); // Hide any previous element..
		this.mouseObserver = this.move.bindAsEventListener(this);
		Event.observe(document, "mousemove", this.mouseObserver);
		this.id = id;
		var cachedElement = this.elements[id];
		if (cachedElement) {
			this.activeElement = cachedElement;
			this.move(event);
			this.activeElement.show();
		} else {
			this.activeElement = this.prepare(id, Event.element(event), width);
			this.activeElement.setContent(markup);
			this.move(event);
			this.activeElement.show();
		}
	},

	show: function(id, url, event, width) {
		this.hide(); // Hide any previous element..
		this.mouseObserver = this.move.bindAsEventListener(this);
		Event.observe(document, "mousemove", this.mouseObserver);
		this.id = id;
		var cachedElement = this.elements[id];
		if (cachedElement) {
			if (Event.element(event) == cachedElement.originatingObject) {
				this.activeElement = cachedElement;
				this.move(event);
				this.activeElement.show();
			} else {
				//console.warn("Invalid originating object \""+ Event.element(event).id +"\" for cached element \""+ id +"\" (\""+ cachedElement.originatingObject.id +"\")");
			}
		} else {
			this.setMouse(event);
			this.elementLoading = this.prepare(id, Event.element(event), width);
			var urlHasParams = (url.indexOf("?") != -1);
			var ajaxURL = urlHasParams ? url.substring(0, url.indexOf("?")) : url;
			var ajaxParams = urlHasParams ? url.substring(url.indexOf("?") + 1) : "";
			new Ajax.Request(
					ajaxURL,
					{
						method: "get",
						parameters: ajaxParams,
						onSuccess: this.elementLoading.handleAjaxResponse.bind(this.elementLoading),
						onFailure: this.elementLoading.handleAjaxFailure.bind(this.elementLoading)
					});
		}
	},
	
	hide: function() {
		if (!this.activeElement)
			return;
		Event.stopObserving(document, "mousemove", this.mouseObserver);
		this.mouseObserver = null;
		this.elementLoading = null; // Cancel loading element
		this.activeElement.hide();
		this.activeElement = null;
	},
	
	elementLoaded: function(element) {
		if (!this.elementLoading || element.id != this.elementLoading.id)
			return;
		this.elementLoading = null;
		this.activeElement = element;
		this.activeElement.position();
		this.activeElement.show();
	},
	
	elementFailed: function(element) {
		this.elementLoaded(element); // Show element containing error message
		this.remove(element); // Remove from elements
	},
	
	setMouse: function(event) {
		this.mouse.lastX = this.mouse.x;
		this.mouse.lastY = this.mouse.y;
		this.mouse.x = Event.pointerX(event);
		this.mouse.y = Event.pointerY(event);
	},
	
	move: function(event) {
		if (this.activeElement) {
			if (Event.element(event) == this.activeElement.originatingObject) {
				this.setMouse(event);
				if (this.mouse.x != this.mouse.lastX || this.mouse.y != this.mouse.lastY)
					this.activeElement.position();
			} else {
				this.hide();
			}
		}
	}
}

// ================================================================================================
// Positionable
// ------------------------------------------------------------------------------------------------

var Positionable = {

	setContent: function(content) {
		this.content.update(content);
	},

	position: function() {
		var dim = this.container.getDimensions();
		var x = Hover.mouse.x - dim.width - 10;
		if (x < 10)
			x = 10;
		var y = Hover.mouse.y - dim.height - 10;
		if (y < 10)
			y = 10;
		var mouseWithinX = (Hover.mouse.x > x && Hover.mouse.x < x + dim.width);
		var mouseWithinY = (Hover.mouse.y > y && Hover.mouse.y < y + dim.height);
		if (mouseWithinX && mouseWithinY) {
			if (mouseWithinX)
				x = Hover.mouse.x + 10;
			if (mouseWithinY)
				y = Hover.mouse.y + 10;
		}
		this.container.style.left = x +"px";
		this.container.style.top = y +"px";
		if (Hover.shim != null) {
			Hover.shim.style.left = x +"px";
			Hover.shim.style.top = y +"px";
		}
	},
	
	show: function() {
		if (Hover.shim != null) {
			var dim = this.container.getDimensions();
			var s = Hover.shim;
			s.style.left = this.container.style.left;
			s.style.top = this.container.style.top;
			s.style.width = dim.width +"px";
			s.style.height = dim.height +"px";
			s.show();
		}
		var options = this.sifrDone ? { } : { afterUpdate: this.replaceFonts.bind(this) };
		this.appearEffect = new Effect.Appear(this.container, options);
	},
	
	hide: function() {
		if (typeof this.appearEffect != "undefined" && this.appearEffect != null) {
			this.appearEffect.cancel();
			this.appearEffect = null;
		}
		this.container.hide();
		if (Hover.shim != null)
			Hover.shim.hide();
	},
	
	replaceFonts: function() {
		if (this.sifrDone)
			return;
		mySifr.replaceAll();
		this.sifrDone = true;
	}

}

// ================================================================================================
// HoverElement
// ------------------------------------------------------------------------------------------------

var HoverElement = Class.create();

HoverElement.prototype = {

	initialize: function(id, originatingObject, width) {
		Hover.init();

		this.id = id;
		this.originatingObject = originatingObject;
		
		var cr = this.container = $(document.createElement("div"));
		cr.id = "hoverContainer"+ this.id;
		cr.addClassName("hoverContainer");
		cr.hide();
		
		var fr = this.frame = $(document.createElement("div"));
		fr.id = "hoverFrame"+ this.id;
		fr.addClassName("hoverFrame");
		cr.appendChild(fr);
	
		var ct = this.content = $(document.createElement("div"));
		ct.id = "hoverContent"+ this.id;
		if (width)
			ct.style.width = width +"px";
		ct.addClassName("hoverContent");
		fr.appendChild(ct);
	},
	
	handleAjaxResponse: function(ajaxResponse) {
		this.setContent(ajaxResponse.responseText);
		Hover.elementLoaded(this);
	},
	
	handleAjaxFailure: function(ajaxResponse) {
		this.setContent(this.id, common_hover_informationEjLaddad);
		Hover.elementFailed(this);
	}
	
}

Object.extend(HoverElement.prototype, Positionable);

// ================================================================================================
// Tooltip
// ------------------------------------------------------------------------------------------------

var Tooltip = Class.create();

Tooltip.prototype = {

	originatingObject: null,

	initialize: function() {
		Hover.init();
	
		this.id = "tooltip";
		
		var cr = this.container = $(document.createElement("div"));
		cr.id = "tooltipContainer"+ this.id;
		cr.addClassName("tooltipContainer");
		
		var ct = this.content = $(document.createElement("div"));
		ct.id = "tooltipContent"+ this.id;
		ct.addClassName("tooltipContent");
		cr.appendChild(ct);
	}
}

Object.extend(Tooltip.prototype, Positionable);

Event.onReady(function() {
	$A(document.getElementsByClassName("tooltip")).each(function(el) {
		el = $(el);
		var msg = el.title;
		var f = function(event) { Hover.showTooltip(msg, event); };
		el.observe("mouseover", f.bindAsEventListener(el));
		el.observe("mouseout", function() { Hover.hide(); });
		el.removeAttribute("title");
	});
});
