/*! $Id: toolTip.js 5366 2009-07-22 18:21:25Z bhillebrand $ */
/*global $: false, window: false */
var oCustomToolTip = {
	contentGetter: null,
	xPosition: 'right',
	yPosition: 'top',
	triggerClass: 'toolTip',
	setTriggerClass: function (triggerClass) {
		this.triggerClass = triggerClass;
	},
	setAlignment: function () {
		for (var i = 0; i < arguments.length; i += 1) {
			if (arguments[i] === 'left' || arguments[i] === 'right') {
				this.xPosition = arguments[i];
			} else if (arguments[i] === 'top' || arguments[i] === 'bottom') {
				this.yPosition = arguments[i];
			}
		}
	},
	init: function (tipOffsetX, tipOffsetY) {
		function readOffsetParam(offsetValue, defaultValue) {
			if (typeof(offsetValue) !== 'undefined') {
				if (typeof(offsetValue) === 'string' && offsetValue.charAt(offsetValue.length - 1) === '%') {
					return {isPixelValue: false, value: parseFloat(offsetValue) / 100};
				} else if (!isNaN(parseInt(offsetValue, 10))) {
					return {isPixelValue: true, value: parseInt(offsetValue, 10)};
				} else {
					return {isPixelValue: true, value: defaultValue};
				}
			}
			return {isPixelValue: false, value: 1};
		}
		var toolTipTriggerClass = this.triggerClass,
			oOffsetX = readOffsetParam(tipOffsetX, 10),
			oOffsetY = readOffsetParam(tipOffsetY, 50),

			contentGetter = this.contentGetter,
			xPosition = this.xPosition,
			yPosition = this.yPosition,

			// Create ToolTip nodes
			$toolTip = $(
			'<div id="toolTipMS">' +
				'<div class="alignmentWrp">' +
					'<div class="tipTop">' +
						'<div class="tipBottom">' +
							'<div class="tipContent"></div>' +
						'</div>' +
					'</div>' +
					'<div class="toolTipMSArrow"></div>' +
				'</div>' +
			'</div>'
		).css({
				position: 'absolute',
				float: 'left',
				display: 'none'
			}
		).appendTo("body");

		$('.' + toolTipTriggerClass).hover(function (e) {
			var target  = $(e.target).hasClass(toolTipTriggerClass) ? $(e.target) : $(e.target).closest('.' + toolTipTriggerClass),
				content = ($.isFunction(contentGetter)) ? contentGetter(target.attr('id')) : '',

				$win    = $(window),
				posLeft = 0,
				posTop  = 0,
				viewportClickPosX = e.pageX - $win.scrollLeft(),
				viewportClickPosY = e.pageY - $win.scrollTop(),
				clickMarginRight  = $win.width()  - viewportClickPosX,
				clickMarginBottom = $win.height() - viewportClickPosY,
				xInverted = false,
				yInverted = false,
				$tipArrow,
				bubbleAlignmentClasses = [];

			$(".tipContent", $toolTip).empty().append(content);

			tipOffsetX = oOffsetX.isPixelValue ? oOffsetX.value : Math.round(oOffsetX.value * $toolTip.outerWidth());
			tipOffsetY = oOffsetY.isPixelValue ? oOffsetY.value : Math.round(oOffsetY.value * $toolTip.outerHeight());
			if (xPosition === 'right') {
				// toolTip offset is relative to the left edge of the tooltip
				if (clickMarginRight >= $toolTip.outerWidth() + tipOffsetX) {
					posLeft = (e.pageX + tipOffsetX);
				} else if (viewportClickPosX >= $toolTip.outerWidth() + tipOffsetX) {
					posLeft = (e.pageX - tipOffsetX - $toolTip.outerWidth());
					xInverted = true;
				} else if (Math.max(viewportClickPosX, clickMarginRight) >= $toolTip.outerWidth()) {
					if (viewportClickPosX > clickMarginRight) {
						posLeft = $win.scrollLeft();
						xInverted = true;
					} else {
						posLeft = e.pageX;
					}
				} else {
					posLeft = (e.pageX + tipOffsetX);
				}
			} else {
				// toolTip offset is relative to the right edge of the tooltip (inverted)
				if (viewportClickPosX >= $toolTip.outerWidth() + tipOffsetX) {
					posLeft = (e.pageX - tipOffsetX - $toolTip.outerWidth());
					xInverted = true;
				} else if (clickMarginRight >= $toolTip.outerWidth() + tipOffsetX) {
					posLeft = (e.pageX + tipOffsetX);
				} else if (Math.max(viewportClickPosX, clickMarginRight) >= $toolTip.outerWidth()) {
					if (viewportClickPosX > clickMarginRight) {
						posLeft = $win.scrollLeft();
						xInverted = true;
					} else {
						posLeft = e.pageX;
					}
				} else {
					posLeft = (e.pageX - tipOffsetX - $toolTip.outerWidth());
					xInverted = true;
				}
			}

			if (yPosition === 'bottom') {
				// toolTip offset is relative to the top edge of the tooltip
				if (clickMarginBottom >= $toolTip.outerHeight() + tipOffsetY) {
					posTop = (e.pageY + tipOffsetY);
				} else if (viewportClickPosY >= $toolTip.outerHeight() + tipOffsetY) {
					posTop = (e.pageY - tipOffsetY - $toolTip.outerHeight());
					yInverted = true;
				} else if (Math.max(viewportClickPosY, clickMarginBottom) >= $toolTip.outerHeight()) {
					if (viewportClickPosY > clickMarginBottom) {
						posTop = $win.scrollTop();
						yInverted = true;
					} else {
						posTop = e.pageY;
					}
				} else {
					posTop = (e.pageY + tipOffsetY);
				}
			} else {
				// toolTip offset is relative to the bottom edge of the tooltip  (inverted)
				if (viewportClickPosY >= $toolTip.outerHeight() + tipOffsetY) {
					posTop = (e.pageY - tipOffsetY - $toolTip.outerHeight());
					yInverted = true;
				} else if (clickMarginBottom >= $toolTip.outerHeight() + tipOffsetY) {
					posTop = (e.pageY + tipOffsetY);
				} else if (Math.max(viewportClickPosY, clickMarginBottom) >= $toolTip.outerHeight()) {
					if (viewportClickPosY > clickMarginBottom) {
						posTop = $win.scrollTop();
						yInverted = true;
					} else {
						posTop = e.pageY;
					}
				} else {
					posTop = (e.pageY - tipOffsetY - $toolTip.outerHeight());
				}
			}
			if (xInverted) {
				bubbleAlignmentClasses.push("leftAligned");
			}
			if (!yInverted) {
				bubbleAlignmentClasses.push("topAligned");
			}
			$tipArrow = $(".toolTipMSArrow", $toolTip);
			$tipArrow.css({
				left: 'auto',
				right: 'auto',
				bottom: 'auto'
			});
			$tipArrow.css(!xInverted ? {left: '0px'} : {right: '0px'});
			$(".alignmentWrp", $toolTip).removeClass("leftAligned topAligned").addClass(bubbleAlignmentClasses.join(" "));
			$toolTip.css({left: posLeft + 'px', top: posTop + 'px'}).show();
			/* $tipArrow.outerHeight() will return 0 as long as the tooltip is hidden */
			$tipArrow.css({top: (!yInverted ? - $tipArrow.outerHeight() / 2 + 1 - tipOffsetY : $toolTip.outerHeight() - $tipArrow.outerHeight() / 2 - 1 + tipOffsetY) + 'px'});
		},
		function (e) {
			$toolTip.hide().find(".tipContent").empty();
		});
	},
	setContentGetter: function (func) {
		this.contentGetter = func;
	}
};