adobe.Loader.requireAsset("_/module/tooltip/tooltip.css");

adobe.Idiom = {};

adobe.Idiom.Localize = function(data) { return data; }

/*--- 
	adobe.Idiom.Localize(data) is a function wrapper to indicate to Idiom translate the variable text passed in:
		
		var tooltips_data = {
			"lorem-tip":   { "TOOLTIP_DESC": Localize("This text here gets translated by Idiom") },
			"lorem-tip-2": { "TOOLTIP_DESC": Localize("This text here gets translated by Idiom") }
		}
---*/

function createTooltip() {
	var pane = new Element("div").setStyle({
						position:"absolute",
						top:"0",
						left:"0",
						border:"1px solid"
					});
	return pane;
}

function init_Tooltips() {
	var peekLinks = $$("a.dyn-tooltip");
	if (!window.tooltips_data) { return }
	var datamanager = new TooltipDataManager(tooltips_data);
	var renderer = new TooltipRenderer();
	var currentPeekID;
	var currentPeekState;
	var _timer = null;
	
	function showTooltip(event) {
		
		if(!Event.element(event)) return;
		
		var el = Event.element(event);
		
		//if element is an image, grab <a> above it
		//Bug 76345: Safari 2.0.1 and below, has to use parentNode of el or else just returns textNode
		if(el.nodeName == "IMG" || (adobe.hostEnv.isSafari && adobe.hostEnv.kitV <= 413)) { el = el.parentNode; }	
		
		var id = el.id;		
		
		if(id == currentPeekID && currentPeekState == "show") { return; }
		
		currentPeekID = id;
		currentPeekState = "show";
		
		var pos = el.className.match(/panePos-(.)/) || "";
		
		if(pos) {
			pos = pos[1];
		}
		
		var data = datamanager.getData(id);
		if(!data) { return hideTooltip(event); }
		
		var sOffset = Position.realOffset(document.body),
		html = (document.compatMode == "CSS1Compat") ? document.body.parentNode : document.body,
		contentH = window.clientHeight || html.clientHeight,
		contentW = window.clientWidth || html.clientWidth,
		viewportL = sOffset[0],
		viewportT = sOffset[1],
		viewportR = contentW + viewportL,
		viewportB = contentH + viewportT;
		
		
		renderer.setContent(id, data);
		renderer.moveToElement(el,pos, {
			buffer:10,
			safeArea: [viewportT,viewportR,viewportB,viewportL]
		});
		
		_timer = window.setTimeout(renderer.show.bind(renderer), 500);
	
	}
	
	function hideTooltip(event) {
		if(!Event.element(event)) return;
		
		var el = Event.element(event);	
		
		//if element is an image, grab <a> above it
		//bug 76407: safari 2.0.4 has issues hiding this element 
		if(el.nodeName == "IMG" || (adobe.hostEnv.isSafari && adobe.hostEnv.kitV <= 413)) { el = el.parentNode; }	
		
		var id = el.id;
		if(id != currentPeekID) { return; }
		if(currentPeekState == "show") {
			window.clearTimeout(_timer);
			renderer.hide();
			currentPeekState = "hide";
		}			
	}
	
	
	function showState() {
		adobe.Console.log(currentPeekID + " is in " + currentPeekState + " state");
	}		
	
	for(var i=0, tip;i<peekLinks.length;i++) {
		tip = peekLinks[i];
		Event.observe(tip, "mouseover", showTooltip);
		Event.observe(tip, "mouseout", hideTooltip);
	}

}

TooltipDataManager = function(data) {
	this.data = data;
}

TooltipDataManager.prototype = {
	getData: function(id) {
		return this.data[id]
	}
};

TooltipRenderer = function() {
	this.template = null;
	this.container = null;
	this.pane = null;
	this.paneStyle = "tooltip";
	this.rendered = false;
	this.visible = false;
	this.shown = false;
	this.rendered_content = {};
}

TooltipRenderer.prototype = {
	createContainer: function() {
		var pane = this.getPane()
				.insert(this.container = new Element("div").addClassName("tooltipBody"))
				.insert(this.pointer = new Element("div").addClassName("pointer"))
		;
		
		return this.container;
	},
	createPane: function() {
		return (this.pane = new Element("div").addClassName(this.paneStyle));
	},
	createTemplate: function(id,data) {
		
		var title = "";
		var desc = "";
					
		if (data['TOOLTIP_TITLE']) { title += '<span class="tipTitle">#TOOLTIP_TITLE#<\/span>' }
		if (data['TOOLTIP_DESC']) { desc += '<span class="tipDesc">#TOOLTIP_DESC#<\/span>' }
	
		this.template = new adobe.ContentTemplate(([title,desc].join("")));
	
	return this.template;

	},
	moveTo:function(x, y) {
		container = this.getPane();
		container.style.left = (x+"px");
		container.style.top = (y+"px");
	},
	moveToElement: function(el, align, option) {					
		
		if(!this.rendered) {
			this.hide();
			this.render(adobe.Element.getOwnerDocument(el).body);
		}
		
		var pos = Position.cumulativeOffset(el),
		buffer = option.buffer,
		elemL =  pos[0],
		elemT = pos[1],
		paneL = elemL,
		paneT = elemT,
		u = "px",
		buffer = 0 || buffer,
		pane = this.getPane(),
		pointer = this.pointer,
		pointerW = parseInt(pointer.offsetWidth),
		pointerH = parseInt(pointer.offsetHeight),
		elemW = parseInt(el.offsetWidth),
		elemH = parseInt(el.offsetHeight),
		paneW = parseInt(pane.offsetWidth),
		paneH = parseInt(pane.offsetHeight),
		paneStyle = this.paneStyle,
		safe =  option.safeArea;
		
		
		function _rightcorner() {
			return elemL + elemW - paneW;
		}
		
		function _bottomcorner() {
			return elemT + elemH - paneH;
		}
		
		function _l() {
			return elemL - paneW - buffer;
		}
		
		function _m() {
			return elemT + (elemH/2) - (paneH/2) ;
		}
		
		function _r() {
			return elemL + elemW + buffer;
		}
		
		function _getPointerH() {
			return pointerH || (pointerH = parseInt(pointer.offsetHeight));
		}
		
		function _getPointerX() {
			return (elemL - paneL) + u;
		}
		
		function _getPointerY() {
			var elemC = (elemT + elemH/2),
			pointerC = (_getPointerH()/2);
			return (elemC - paneT -  pointerC) + u;
		}
		
		function _getOverflow(insideBound, outsideBound, test) {
			var result;
			
			switch(test) {
				case "more":
					result = (insideBound > outsideBound) ? Math.round((outsideBound - insideBound)) : 0;
					break;
				case "less":
					result = (insideBound < outsideBound) ? Math.round(Math.abs((outsideBound - insideBound))) : 0;
					break;
			}
			
			return result;
		}
				
		if(align) {
			
			var paneReg = {
				t:_m(),
				r:_r(),
				l:_l()
			}
			
			paneT = paneReg.t;
			
			
			switch( align ) {
				case "r": paneL = paneReg.r; break;
				case "l": paneL = paneReg.l; break;
			}
			
			if(safe && safe.length == 4) {
				
				var paneBound = {
					t: paneReg.t,
					l: paneReg.l,
					r: paneReg.r+paneW,
					b: paneReg.t+paneH
				};
				
				var over = {
					t:_getOverflow(paneBound.t, safe[0], "less"),
					r:_getOverflow(paneBound.r, safe[1], "more"),
					b:_getOverflow(paneBound.b, safe[2], "more"),
					l:_getOverflow(paneBound.l, safe[3], "less")
				}
				
				// left and right detection
				if(over.r && !over.l && !adobe.hostEnv.isSafari) {
					paneL = paneReg.l;
					align = "l";
				} else if(over.l && !over.r) {
					paneL = paneReg.r;
					align = "r";
				}
			
				//top and bottom detection
				if(over.t && !over.b) {
					var shiftDownOver = _getOverflow(paneBound.b + over.t, "b"); //check for a shift down
					if(!shiftDownOver) {
						paneT = paneT + over.t;
					}

				} else if(over.b && !over.t) {
					var shiftUpOver = _getOverflow(paneBound.b + over.t, "t");
					
					if(!shiftUpOver) {
						paneT = paneT + over.b;
					}
				}
					
			}
			
			pane.className = paneStyle + " " + align;
			
			pointer.style.top = _getPointerY();
		}
		
		this.moveTo(paneL, paneT);
		
	},
	setContent: function(id, data) {
		this.rendered_content[id] = this.rendered_content[id] || (this.template || this.createTemplate(id,data)).injectData(data);
		this.getContainer().innerHTML = this.rendered_content[id];
	},
	getContainer: function() {
		return (this.container || this.createContainer());
	},
	getPane: function() {
		return (this.pane || this.createPane());
	},
	render: function(element) {
		this.rendered = !!element.appendChild(this.getPane());
		this.visible = (this.rendered && this.shown);
	},
	setHeight: function(px) {
		var pane = this.getPane();
		pane.style.height = ((!px) ? "" : (px + "px"));
	},
	setWidth: function(px) {
		var pane = this.getPane();
		pane.style.width = ((!px) ? "" : (px + "px"));
	},
	show: function() {
		var pane = this.getPane();
		pane.style.visibility="visible";
		this.setHeight(pane.offsetHeight);
		this.shown = true;
		this.visible = this.rendered;
	},
	hide: function() {
		var pane = this.getPane();
		pane.style.visibility="hidden";
		this.setHeight();
		this.shown = false;
	}
}
