////////////////////////////////////////////////////////////////////////////////
// Constants
////////////////////////////////////////////////////////////////////////////////

var __CFTOOLTIP_ERROR_ID = "invalid CFToolTip id";

var __CFTOOLTIP_SCROLLBAR_ALLOWANCE = 20;
var __CFTOOLTIP_X_OFFSET = 15;
var __CFTOOLTIP_Y_OFFSET = 25;
var __CFTOOLTIP_BOTTOM_OFFSET = __CFTOOLTIP_SCROLLBAR_ALLOWANCE +
                                __CFTOOLTIP_X_OFFSET;
var __CFTOOLTIP_RIGHT_OFFSET = __CFTOOLTIP_SCROLLBAR_ALLOWANCE +
                               __CFTOOLTIP_Y_OFFSET;

////////////////////////////////////////////////////////////////////////////////
// Static Variables
////////////////////////////////////////////////////////////////////////////////

var __cfToolTipMap = {};

////////////////////////////////////////////////////////////////////////////////
// Classes
////////////////////////////////////////////////////////////////////////////////

function CFToolTip(id, mouseOverId)
{
    CFPopup.call(this, id);
    var mouseOverElement = cfElementGet(mouseOverId);
    mouseOverElement.title = '';
    this.__mouseShow = false;
    __cfToolTipMap[id] = this;
    var f = cfEventHandlerCreate(this.hide.bind(this));
    mouseOverElement.onblur = f;
    mouseOverElement.onmouseout = f;
    f = cfEventHandlerCreate(this.__move.bind(this));
    mouseOverElement.onmousemove = f;
    f = cfEventHandlerCreate(this.__showFocus.bind(this));
    mouseOverElement.onfocus = f;
    f = cfEventHandlerCreate(this.__showMouse.bind(this));
    mouseOverElement.onmouseover = f;
}

CFToolTip.extendClasses(CFPopup);

CFToolTip.prototype.__move = function()
{
    var toolTipDimensions = this.getDimensions(true);
    if (toolTipDimensions) {
        var mousePosition = cfMouseGetDocumentPosition(true);
        if (mousePosition) {
            var mousePositionX = mousePosition.x;
            var mousePositionY = mousePosition.y;
            var left = mousePositionX + __CFTOOLTIP_X_OFFSET;
            var top = mousePositionY + __CFTOOLTIP_Y_OFFSET;
            var viewportPosition = cfMouseGetViewportPosition();
            var viewportDimensions = cfViewportGetDimensions();
            var toolTipWidth = toolTipDimensions.width;
            if (viewportDimensions.width < (viewportPosition.x + toolTipWidth +
                                            __CFTOOLTIP_RIGHT_OFFSET)) {
                left = mousePositionX - (__CFTOOLTIP_X_OFFSET + toolTipWidth);
            }
            var toolTipHeight = toolTipDimensions.height;
            if (viewportDimensions.height <
                (viewportPosition.y + toolTipHeight +
                 __CFTOOLTIP_BOTTOM_OFFSET)) {
                top = mousePositionY - (__CFTOOLTIP_Y_OFFSET + toolTipHeight);
            }
            this.setTopLeftPosition(top, left);
            return false;
        }
    }
}

CFToolTip.prototype.__show = function()
{
    CFPopup.prototype.__show.call(this);
    if (this.__mouseShow) {
        this.__move();
    }
}

CFToolTip.prototype.__showFocus = function()
{
    this.setTopLeftPosition(undefined, undefined);
    this.show();
    return false;
}

CFToolTip.prototype.__showMouse = function()
{
    this.__mouseShow = true;
    this.show();
    return false;
}

CFToolTip.prototype.hide = function()
{
    CFPopup.prototype.hide.call(this);
    this.__mouseShow = false;
    return false;
}

////////////////////////////////////////////////////////////////////////////////
// Public API
////////////////////////////////////////////////////////////////////////////////

function cfToolTipCreate(arg)
{
    return new CFToolTip(arg.id, arg.mouseOverId);
}

function cfToolTipGet(id)
{
    var toolTip = __cfToolTipMap[id];
    if (! toolTip) {
        return cfErrorTrigger("cfToolTipGet: '" + id + "': " +
                              __CFTOOLTIP_ERROR_ID);
    }
    return toolTip;
}
