/*
 * Copyright (C) 2009 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @constructor
 * @extends {WebInspector.View}
 * @param {!WebInspector.PopoverHelper=} popoverHelper
 */
WebInspector.Popover = function(popoverHelper)
{
    WebInspector.View.call(this);
    this.markAsRoot();
    this.element.className = "popover custom-popup-vertical-scroll custom-popup-horizontal-scroll";

    this._popupArrowElement = document.createElement("div");
    this._popupArrowElement.className = "arrow";
    this.element.appendChild(this._popupArrowElement);

    this._contentDiv = document.createElement("div");
    this._contentDiv.className = "content";
    this.element.appendChild(this._contentDiv);

    this._popoverHelper = popoverHelper;
}

WebInspector.Popover.prototype = {
    /**
     * @param {!Element} element
     * @param {!Element|!AnchorBox} anchor
     * @param {?number=} preferredWidth
     * @param {?number=} preferredHeight
     * @param {?WebInspector.Popover.Orientation=} arrowDirection
     */
    show: function(element, anchor, preferredWidth, preferredHeight, arrowDirection)
    {
        this._innerShow(null, element, anchor, preferredWidth, preferredHeight, arrowDirection);
    },

    /**
     * @param {!WebInspector.View} view
     * @param {!Element|!AnchorBox} anchor
     * @param {?number=} preferredWidth
     * @param {?number=} preferredHeight
     */
    showView: function(view, anchor, preferredWidth, preferredHeight)
    {
        this._innerShow(view, view.element, anchor, preferredWidth, preferredHeight);
    },

    /**
     * @param {?WebInspector.View} view
     * @param {!Element} contentElement
     * @param {!Element|!AnchorBox} anchor
     * @param {?number=} preferredWidth
     * @param {?number=} preferredHeight
     * @param {?WebInspector.Popover.Orientation=} arrowDirection
     */
    _innerShow: function(view, contentElement, anchor, preferredWidth, preferredHeight, arrowDirection)
    {
        if (this._disposed)
            return;
        this.contentElement = contentElement;

        // This should not happen, but we hide previous popup to be on the safe side.
        if (WebInspector.Popover._popover)
            WebInspector.Popover._popover.detach();
        WebInspector.Popover._popover = this;

        // Temporarily attach in order to measure preferred dimensions.
        var preferredSize = view ? view.measurePreferredSize() : this.contentElement.measurePreferredSize();
        preferredWidth = preferredWidth || preferredSize.width;
        preferredHeight = preferredHeight || preferredSize.height;

        WebInspector.View.prototype.show.call(this, document.body);

        if (view)
            view.show(this._contentDiv);
        else
            this._contentDiv.appendChild(this.contentElement);

        this._positionElement(anchor, preferredWidth, preferredHeight, arrowDirection);

        if (this._popoverHelper) {
            this._contentDiv.addEventListener("mousemove", this._popoverHelper._killHidePopoverTimer.bind(this._popoverHelper), true);
            this.element.addEventListener("mouseout", this._popoverHelper._popoverMouseOut.bind(this._popoverHelper), true);
        }
    },

    hide: function()
    {
        this.detach();
        delete WebInspector.Popover._popover;
    },

    get disposed()
    {
        return this._disposed;
    },

    dispose: function()
    {
        if (this.isShowing())
            this.hide();
        this._disposed = true;
    },

    setCanShrink: function(canShrink)
    {
        this._hasFixedHeight = !canShrink;
        this._contentDiv.classList.add("fixed-height");
    },

    /**
     * @param {!Element|!AnchorBox} anchorElement
     * @param {number} preferredWidth
     * @param {number} preferredHeight
     * @param {?WebInspector.Popover.Orientation=} arrowDirection
     */
    _positionElement: function(anchorElement, preferredWidth, preferredHeight, arrowDirection)
    {
        const borderWidth = 25;
        const scrollerWidth = this._hasFixedHeight ? 0 : 11;
        const arrowHeight = 15;
        const arrowOffset = 10;
        const borderRadius = 10;

        // Skinny tooltips are not pretty, their arrow location is not nice.
        preferredWidth = Math.max(preferredWidth, 50);
        const totalWidth = window.innerWidth;
        const totalHeight = window.innerHeight;

        var anchorBox = anchorElement instanceof AnchorBox ? anchorElement : anchorElement.boxInWindow(window);
        var newElementPosition = { x: 0, y: 0, width: preferredWidth + scrollerWidth, height: preferredHeight };

        var verticalAlignment;
        var roomAbove = anchorBox.y;
        var roomBelow = totalHeight - anchorBox.y - anchorBox.height;

        if ((roomAbove > roomBelow) || (arrowDirection === WebInspector.Popover.Orientation.Bottom)) {
            // Positioning above the anchor.
            if ((anchorBox.y > newElementPosition.height + arrowHeight + borderRadius) || (arrowDirection === WebInspector.Popover.Orientation.Bottom))
                newElementPosition.y = anchorBox.y - newElementPosition.height - arrowHeight;
            else {
                newElementPosition.y = borderRadius;
                newElementPosition.height = anchorBox.y - borderRadius * 2 - arrowHeight;
                if (this._hasFixedHeight && newElementPosition.height < preferredHeight) {
                    newElementPosition.y = borderRadius;
                    newElementPosition.height = preferredHeight;
                }
            }
            verticalAlignment = WebInspector.Popover.Orientation.Bottom;
        } else {
            // Positioning below the anchor.
            newElementPosition.y = anchorBox.y + anchorBox.height + arrowHeight;
            if ((newElementPosition.y + newElementPosition.height + arrowHeight - borderWidth >= totalHeight) && (arrowDirection !== WebInspector.Popover.Orientation.Top)) {
                newElementPosition.height = totalHeight - anchorBox.y - anchorBox.height - borderRadius * 2 - arrowHeight;
                if (this._hasFixedHeight && newElementPosition.height < preferredHeight) {
                    newElementPosition.y = totalHeight - preferredHeight - borderRadius;
                    newElementPosition.height = preferredHeight;
                }
            }
            // Align arrow.
            verticalAlignment = WebInspector.Popover.Orientation.Top;
        }

        var horizontalAlignment;
        if (anchorBox.x + newElementPosition.width < totalWidth) {
            newElementPosition.x = Math.max(borderRadius, anchorBox.x - borderRadius - arrowOffset);
            horizontalAlignment = "left";
        } else if (newElementPosition.width + borderRadius * 2 < totalWidth) {
            newElementPosition.x = totalWidth - newElementPosition.width - borderRadius;
            horizontalAlignment = "right";
            // Position arrow accurately.
            var arrowRightPosition = Math.max(0, totalWidth - anchorBox.x - anchorBox.width - borderRadius - arrowOffset);
            arrowRightPosition += anchorBox.width / 2;
            arrowRightPosition = Math.min(arrowRightPosition, newElementPosition.width - borderRadius - arrowOffset);
            this._popupArrowElement.style.right = arrowRightPosition + "px";
        } else {
            newElementPosition.x = borderRadius;
            newElementPosition.width = totalWidth - borderRadius * 2;
            newElementPosition.height += scrollerWidth;
            horizontalAlignment = "left";
            if (verticalAlignment === WebInspector.Popover.Orientation.Bottom)
                newElementPosition.y -= scrollerWidth;
            // Position arrow accurately.
            this._popupArrowElement.style.left = Math.max(0, anchorBox.x - borderRadius * 2 - arrowOffset) + "px";
            this._popupArrowElement.style.left += anchorBox.width / 2;
        }

        this.element.className = "popover custom-popup-vertical-scroll custom-popup-horizontal-scroll " + verticalAlignment + "-" + horizontalAlignment + "-arrow";
        this.element.positionAt(newElementPosition.x - borderWidth, newElementPosition.y - borderWidth);
        this.element.style.width = newElementPosition.width + borderWidth * 2 + "px";
        this.element.style.height = newElementPosition.height + borderWidth * 2 + "px";
    },

    __proto__: WebInspector.View.prototype
}

/**
 * @constructor
 * @param {!Element} panelElement
 * @param {function(!Element, !Event):(!Element|!AnchorBox)|undefined} getAnchor
 * @param {function(!Element, !WebInspector.Popover):undefined} showPopover
 * @param {function()=} onHide
 * @param {boolean=} disableOnClick
 */
WebInspector.PopoverHelper = function(panelElement, getAnchor, showPopover, onHide, disableOnClick)
{
    this._panelElement = panelElement;
    this._getAnchor = getAnchor;
    this._showPopover = showPopover;
    this._onHide = onHide;
    this._disableOnClick = !!disableOnClick;
    panelElement.addEventListener("mousedown", this._mouseDown.bind(this), false);
    panelElement.addEventListener("mousemove", this._mouseMove.bind(this), false);
    panelElement.addEventListener("mouseout", this._mouseOut.bind(this), false);
    this.setTimeout(1000);
}

WebInspector.PopoverHelper.prototype = {
    setTimeout: function(timeout)
    {
        this._timeout = timeout;
    },

    /**
     * @param {!MouseEvent} event
     * @return {boolean}
     */
    _eventInHoverElement: function(event)
    {
        if (!this._hoverElement)
            return false;
        var box = this._hoverElement instanceof AnchorBox ? this._hoverElement : this._hoverElement.boxInWindow();
        return (box.x <= event.clientX && event.clientX <= box.x + box.width &&
            box.y <= event.clientY && event.clientY <= box.y + box.height);
    },

    _mouseDown: function(event)
    {
        if (this._disableOnClick || !this._eventInHoverElement(event))
            this.hidePopover();
        else {
            this._killHidePopoverTimer();
            this._handleMouseAction(event, true);
        }
    },

    _mouseMove: function(event)
    {
        // Pretend that nothing has happened.
        if (this._eventInHoverElement(event))
            return;

        this._startHidePopoverTimer();
        this._handleMouseAction(event, false);
    },

    _popoverMouseOut: function(event)
    {
        if (!this.isPopoverVisible())
            return;
        if (event.relatedTarget && !event.relatedTarget.isSelfOrDescendant(this._popover._contentDiv))
            this._startHidePopoverTimer();
    },

    _mouseOut: function(event)
    {
        if (!this.isPopoverVisible())
            return;
        if (!this._eventInHoverElement(event))
            this._startHidePopoverTimer();
    },

    _startHidePopoverTimer: function()
    {
        // User has 500ms (this._timeout / 2) to reach the popup.
        if (!this._popover || this._hidePopoverTimer)
            return;

        function doHide()
        {
            this._hidePopover();
            delete this._hidePopoverTimer;
        }
        this._hidePopoverTimer = setTimeout(doHide.bind(this), this._timeout / 2);
    },

    _handleMouseAction: function(event, isMouseDown)
    {
        this._resetHoverTimer();
        if (event.which && this._disableOnClick)
            return;
        this._hoverElement = this._getAnchor(event.target, event);
        if (!this._hoverElement)
            return;
        const toolTipDelay = isMouseDown ? 0 : (this._popup ? this._timeout * 0.6 : this._timeout);
        this._hoverTimer = setTimeout(this._mouseHover.bind(this, this._hoverElement), toolTipDelay);
    },

    _resetHoverTimer: function()
    {
        if (this._hoverTimer) {
            clearTimeout(this._hoverTimer);
            delete this._hoverTimer;
        }
    },

    isPopoverVisible: function()
    {
        return !!this._popover;
    },

    hidePopover: function()
    {
        this._resetHoverTimer();
        this._hidePopover();
    },

    _hidePopover: function()
    {
        if (!this._popover)
            return;

        if (this._onHide)
            this._onHide();

        this._popover.dispose();
        delete this._popover;
        this._hoverElement = null;
    },

    _mouseHover: function(element)
    {
        delete this._hoverTimer;

        this._hidePopover();
        this._popover = new WebInspector.Popover(this);
        this._showPopover(element, this._popover);
    },

    _killHidePopoverTimer: function()
    {
        if (this._hidePopoverTimer) {
            clearTimeout(this._hidePopoverTimer);
            delete this._hidePopoverTimer;

            // We know that we reached the popup, but we might have moved over other elements.
            // Discard pending command.
            this._resetHoverTimer();
        }
    }
}

/** @enum {string} */
WebInspector.Popover.Orientation = {
    Top: "top",
    Bottom: "bottom"
}
