if (!SIGI || !SIGI.Parsing) throw ("SIGI.Tooltip depends on the following scripts. Please make sure these are included.\nSIGI.js, SIGI.Parsing");

/********************************************************************/
//	Class Name: ToolTipObject 
//	Purpose:	Represents a single control's tooltip
//	
//	Remarks:	This is created for each control that has a tooltip
//
/********************************************************************/

function TooltipObject(tooltipText) {
    this.StyleParser();
    this.tip = "";
    this.align = "bottom";
    this.type = "tooltip";
    this.width = null;
    this.height = null;
    this.className = "Tooltip";
    this.showTriggered = false;
    this.skipHide = false;
    this.suspended = false;
    this.delayedHide = false;

    if (tooltipText) {
        this.tip = tooltipText;
        this.parseProperties(tooltipText);
    }
}
TooltipObject.inherits(SIGI.Parsing.StyleParser);
TooltipObject.prototype.setType = function(type) {
    if (type) this.type = type;
    switch (this.type) {
        case "critical":
            this.className = "Tooltip_Critical";
            break;
        case "information":
            this.className = "Tooltip_Information";
            break;
        case "exclamation":
            this.className = "Tooltip_Exclamation";
            break;
        case "help": case "question":
            this.className = "Tooltip_Question";
            break;
        default:
            this.className = "Tooltip";
            this.type = "tooltip"
    }
}
TooltipObject.prototype.setProperty = function(propertyName, value) {
    value = value.trim();
    switch (propertyName) {
        case "tip":
            this.tip = value.qtrim();
            break;
        case "type":
            value = value.toLowerCase();
            var re = /(critical|information|exclamation|help|tooltip)/i;
            if (re.test(value)) {
                value = RegExp.$1;
            } else {
                value = "tooltip";
            }
            this.setType(value);
            break;
        case "align":
            value = value.toLowerCase();
            var re = /(left|right|top|bottom)/i;
            if (re.test(value)) {
                value = RegExp.$1;
            } else {
                value = "bottom";
            }
            this.align = value
            break;
        case "width": case "height":
            var re = /\d{1,4}[px|%]/;
            if (re.test(value)) {
                this[propertyName] = value;
            }
            break;
        default:
            this[propertyName] = value;
    }
}
SIGI.TooltipObject = TooltipObject;
TooltipObject = null;



function TooltipControllerObject() {
    this.Base();
    this.offX = 0;
    this.offY = 0;
    this.overlaySelects = true;
    this.supportsOverlay = true;
    this.showDelay = 100;
    this.hideDelay = 200;
    this.tipID = "TooltipDiv";
    this.isReady = false;
    this.timer = null;
    this.ovTimer = 0;
    this.tip = null;
    this.shim = null;
    this.currentElement = null;
    this.hasFocus = false;
    this.EventHandlers = {};
    this.followMouse = false;  // must be turned off for hover-tip
    this.timerId = 0;
    this.isShown = false;
    this.skipNextToggleHide = false;

    SIGI.attachEvent(window, "onload", this.context(this.init));
}
TooltipControllerObject.inherits(SIGI.Base);
TooltipControllerObject.prototype.init = function() {
    var el = document.getElementById(this.tipID);
    if (!el) {
        var el = document.createElement("DIV");
        el.id = this.tipID;
        el.style.position = "absolute";
        el.style.visibility = "hidden";
        el.style.left = "0px";
        el.style.top = "0px";
        el.style.zIndex = 10000;
        el.className = "Error_ToolTip";
        document.body.appendChild(el);
    }
    this.tip = el;

    //SIGI.attachEvent(document, "onmouseover",this.context(this.onmouseover));
    //SIGI.attachEvent(document, "onmouseout",this.context(this.onmouseout));
    SIGI.attachEvent(document, "onfocusin", this.context(this.onfocusin));
    SIGI.attachEvent(document, "onfocusout", this.context(this.onfocusout));
    SIGI.attachEvent(window, "onunload", this.context(this.unHookHover));
    this.isReady = true;
}
TooltipControllerObject.prototype.showOnEvent = function(evt, toolTip) {
    if (this.timer) {
        clearTimeout(this.timer);
        this.timer = 0;
    }
    if (typeof toolTip == "string") {
        toolTip = this.getTooltipObject(toolTip)
    }
    if (toolTip) {
        this.currentElement = evt.srcElement;
        this.__showTooltip(toolTip);
    }
}
TooltipControllerObject.prototype.showForElement = function(element) {
    var toolTip = this.getTooltipObject(element);
    if (toolTip) {
        if (!this.currentElement)
            this.currentElement = element;
        this.clearTimer();
        this.__showTooltip(toolTip);
    }
}
TooltipControllerObject.prototype.showForValidation = function(element, errorMessage, severity, align) {
    var toolTip = new SIGI.TooltipObject();
    toolTip.tip = errorMessage;
    toolTip.align = align;
    toolTip.setType(severity);

    this.clearTimer();
    this.currentElement = element;
    this.__showTooltip(toolTip, true);
}

/*
RTS 1301680
For Composite control, the internal value element is the one being validated
but that is being hidden off-screen, so the tooltip shows at the bottom corner
So, for composite control value elements, position tooltip properly by 
'refocusing currentElement to parent element
*/
TooltipControllerObject.prototype.resolveCurrentElement = function() {
    //for composite control
    elId = this.currentElement.id;
    valLoc = elId.indexOf("_Value");
    if ((valLoc > -1) && ((elId.length - 6) == valLoc)) {
        /*
        RTS 1301860
        Insure that tooltip is pointed to the composite outer shell for positioning purposes
        */
        elId = elId.replace("_Value", "_Composite");
        cmp = $SIGIfind(elId);
        if (cmp) {
            this.currentElement = cmp.get_element();
        }
        else {
            this.currentElement = this.currentElement.parentElement;
        }
    }
    if (this.currentElement.getAttribute("tooltipSubstitute")) {
        this.currentElement = document.getElementById(this.currentElement.getAttribute("tooltipSubstitute"));
    }
}

TooltipControllerObject.prototype.__showTooltip = function(toolTip, nodelay) {
    if (this.timer) {
        clearTimeout(this.timer);
        this.timer = 0;
    }
    this.resolveCurrentElement();
    if (!this.tip) this.tip = document.getElementById(this.tipID);
    this.writeTip("");
    this.writeTip(toolTip);
    SIGI.Window.refresh();
    this.handleOverlay(1, this.showDelay);
    this.positionTip(toolTip);
    var self = this;
    if (nodelay) {
        this.toggleVisibility(this.tipID, "visible");
    } else {
        this.timer = window.setTimeout(function() { self.toggleVisibility.call(self, self.tipID, "visible"); }, this.showDelay);
    }
}
TooltipControllerObject.prototype.hide = function() {
    if (this.delayedHide == true) {
        return;
    }
    this.skipHide = false;
    if (this.timer) {
        clearTimeout(this.timer);
        this.timer = 0;
    }
    this.handleOverlay(0, this.hideDelay);
    var self = this;
    this.timer = window.setTimeout(function() { self.toggleVisibility.call(self, self.tipID, "hidden"); }, this.hideDelay);
    this.currentElement = null;
    this.tip = null;
}
TooltipControllerObject.prototype.suspend = function(val) {
    this.suspended = val;
}
TooltipControllerObject.prototype.toggleVisibility = function(id, visibility) {
    if ((visibility == "visible") && (this.suspended)) {
        return;
    }
    if (this.skipNextToggleHide) {
        skipNextToggleHide = false;
        return;
    }
    var el = document.getElementById(id);
    if (el) {
        el.style.visibility = visibility;
    }
    this.isShown = (visibility == "visible") ? true : false;
}
TooltipControllerObject.prototype.writeTip = function(toolTip) {
    if (this.tip && typeof this.tip.innerHTML != "undefined") {
        this.tip.innerHTML = toolTip.tip;
        this.tip.className = toolTip.className;
    }
}
TooltipControllerObject.prototype.positionTip = function(toolTip) {

    if (this.tip && this.tip.style) {
        var Window = SIGI.Window;
        var x, y;
        if (toolTip.width) this.tip.style.width = toolTip.width;
        if (toolTip.height) this.tip.style.height = toolTip.height;

        var rect = SIGI.getElementPosition(this.currentElement);

        switch (toolTip.align) {
            case "top":
                x = rect.left;
                y = rect.top - this.tip.offsetHeight;
                break;
            case "left":
                x = rect.left - this.tip.offsetWidth;
                y = rect.top;
                break;
            case "right":
                x = rect.right;
                y = rect.top;
                break;
            default:
                x = rect.left;
                y = rect.bottom;
        }

        // Make sure out tip is within the bounds of the window
        if (x + this.tip.offsetWidth + this.offX > Window.width + Window.scrollX) {
            x = x - this.tip.offsetWidth - this.offX;
        } else if (x < 0) {
            x = 0;
        } else {
            x = x + this.offX;
        }

        if (y + this.tip.offsetHeight + this.offY > Window.height + Window.scrollY) {
            y = y - this.tip.offsetHeight - this.offY;
        } else if (y < Window.scrollY) {
            y = Window.height + Window.scrollY - this.tip.offsetHeight;
        } else {
            y = y + this.offY;
        }
        this.tip.style.left = x + "px";
        this.tip.style.top = y + "px";
        // now make sure the tip isn't covering the element
        var rect2 = SIGI.getElementPosition(this.tip);
        if (rect.intersects(rect2)) {
            var rect3 = rect.intersect(rect2);
            this.tip.style.top = rect3.bottom + "px";
        }
    }
    this.positionOverlay();
}
TooltipControllerObject.prototype.handleOverlay = function(visible, delay) {
    if (this.ovTimer) {
        clearTimeout(this.ovTimer);
        this.ovTimer = 0;
    }
    switch (visible) {
        case 1:
            if (this.shim && this.tip) {

                if (!document.getElementById('TooltipShim'))
                    document.body.insertAdjacentHTML("beforeEnd", '<iframe id="TooltipShim" src="' + SIGI.getClientThemePath() + '/Pages/SIGI.blank.htm" style="position:absolute; left:0; top:0; z-index:500; visibility:hidden" scrolling="no" frameborder="0"></iframe>');
                this.shim = document.getElementById('TooltipShim');

                this.shim.style.width = this.tip.offsetWidth + "px";
                this.shim.style.height = this.tip.offsetHeight + "px";
                this.shim.style.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=1);";
                var self = this;
                this.ovTimer = window.setTimeout(function() { self.toggleVisibility.call(self, "TooltipShim", "visible"); }, delay);
            }
            break;
        case 0:
            var self = this;
            this.ovTimer = window.setTimeout(function() { self.toggleVisibility.call(self, "TooltipShim", "hidden"); }, delay);
            if (this.shim) this.shim = null;
            break;
    }
}
TooltipControllerObject.prototype.positionOverlay = function() {
    if (this.shim && this.tip) {
        this.shim.style.left = this.tip.style.left;
        this.shim.style.top = this.tip.style.top;
    }
}
TooltipControllerObject.prototype.tipOutCheck = function(evt) {
    evt = evt ? evt : window.event;
    if (this.tip == null || (this.tip != evt.toElement && !this.tip.contains(evt.toElement))) {
        this.hide();
    }
}
TooltipControllerObject.prototype.clearTimer = function() {
    if (this.timerId) {
        window.clearTimeout(this.timerId);
        this.timerId = 0;
    }
}
TooltipControllerObject.prototype.getTooltipObject = function(el) {
    if (!el) return null;
    if (el.__toolTip != null) return el.__toolTip;
    var tip = el.getAttribute("tooltip");
    if (tip && typeof tip == "string") {
        el.__toolTip = new SIGI.TooltipObject(tip);
    }
    return el.__toolTip ? el.__toolTip : null;
}
TooltipControllerObject.prototype.unHookHover = function() {
    if (ie) {
        document.detachEvent("onmouseover", this.context(this.onmouseover));
        document.detachEvent("onmouseout", this.context(this.onmouseout));
    }
    else {
        document.removeEventListener("onmouseover", this.context(this.onmouseover), true)
        document.removeEventListener("onmouseout", this.context(this.onmouseout), true)
    }
    var tip = document.getElementById(this.tipID);
    if (tip) {
        tip.onmouseover = null;
        tip.onmouseout = null;
        tip = null;
    }
}
TooltipControllerObject.prototype.onmouseover = function() {
    try {
        if (this.hasFocus == true) return;

        if (event.srcElement.disabled)
            if (event.srcElement.disabled == true)
            return;

        var toolTip = this.getTooltipObject(event.srcElement);

        if (toolTip) {
            this.clearTimer();
            var tip = document.getElementById(this.tipID);
            if (tip && tip.onmouseout == null) {
                tip.onmouseout = this.context(this.tipOutCheck);
                tip.onmouseover = this.context(this.clearTimer);
            }
            this.showOnEvent(event, toolTip);
        }

    } catch (ex) { }
}
TooltipControllerObject.prototype.onmouseout = function() {
    if (this.hasFocus == true) return;
    if (this.currentElement && event.srcElement == this.currentElement) {
        this.timerId = setTimeout(this.context(this.hide), 100);
    } else if (!this.currentElement) {
        this.hide();
    }

}
TooltipControllerObject.prototype.onfocusin = function() {
    try {
        /*
        RTS 1301860
        prevent the info tooltip from overriding a validation failure tooltip
        */
        if (SIGI.skipTooltipDueToValFailure) {
            SIGI.skipTooltipDueToValFailure = false;
            return;
        }
        var toolTip = this.getTooltipObject(event.srcElement);

        if (toolTip) {
            this.clearTimer();
            var tip = document.getElementById(this.tipID);
            if (tip && tip.onmouseout == null) {
                tip.onmouseout = this.context(this.tipOutCheck);
                tip.onmouseover = this.context(this.clearTimer);
            }
            this.hasFocus = true;
            this.showOnEvent(event, toolTip);
        }

    } catch (ex) { }
}
TooltipControllerObject.prototype.onfocusout = function() {
    this.hasFocus = false;
    if (this.skipHide == false) {
        if (this.currentElement && event.srcElement == this.currentElement) {
            this.timerId = setTimeout(this.context(this.hide), 100);
        } else if (!this.currentElement) {
            this.hide();
        }
    }
    else {
        this.skipHide = false;
    }

}


SIGI.TooltipControllerObject = TooltipControllerObject;
TooltipControllerObject = null;
SIGI.Tooltip = new SIGI.TooltipControllerObject();
