/*
 * Copyright (C) 2013, 2015 Apple 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:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
 */

WI.Popover = class Popover extends WI.Object
{
    constructor(delegate)
    {
        super();

        this.delegate = delegate;
        this._edge = null;
        this._frame = new WI.Rect;
        this._content = null;
        this._targetFrame = new WI.Rect;
        this._anchorPoint = new WI.Point;
        this._preferredEdges = null;
        this._resizeHandler = null;

        this._contentNeedsUpdate = false;
        this._dismissing = false;

        this._element = document.createElement("div");
        this._element.className = "popover";
        this._element.addEventListener("transitionend", this, true);

        this._container = this._element.appendChild(document.createElement("div"));
        this._container.className = "container";

        this._drawBackgroundAnimationIdentifier = undefined;
    }

    // Public

    get element() { return this._element; }

    get visible()
    {
        return this._element.parentNode === document.body && !this._element.classList.contains(WI.Popover.FadeOutClassName);
    }

    get frame()
    {
        return this._frame;
    }

    set frame(frame)
    {
        this._element.style.left = frame.minX() + "px";
        this._element.style.top = frame.minY() + "px";
        this._element.style.width = frame.size.width + "px";
        this._element.style.height = frame.size.height + "px";
        this._element.style.backgroundSize = frame.size.width + "px " + frame.size.height + "px";
        this._frame = frame;
    }

    set content(content)
    {
        if (content === this._content)
            return;

        this._content = content;

        this._contentNeedsUpdate = true;

        if (this.visible)
            this._update(true);
    }

    set windowResizeHandler(resizeHandler)
    {
        console.assert(typeof resizeHandler === "function");
        this._resizeHandler = resizeHandler;
    }

    resize()
    {
        if (this.visible && this._resizeHandler)
            this._resizeHandler();
    }

    update(shouldAnimate = true)
    {
        if (!this.visible)
            return;

        var previouslyFocusedElement = document.activeElement;

        this._contentNeedsUpdate = true;
        this._update(shouldAnimate);

        if (previouslyFocusedElement)
            previouslyFocusedElement.focus();
    }

    present(targetFrame, preferredEdges)
    {
        this._targetFrame = targetFrame;
        this._preferredEdges = preferredEdges;

        if (!this._content)
            return;

        this._addListenersIfNeeded();

        this._update();
    }

    presentNewContentWithFrame(content, targetFrame, preferredEdges)
    {
        this._content = content;
        this._contentNeedsUpdate = true;

        this._targetFrame = targetFrame;
        this._preferredEdges = preferredEdges;

        this._addListenersIfNeeded();

        var shouldAnimate = this.visible;
        this._update(shouldAnimate);
    }

    dismiss()
    {
        if (this._dismissing || this._element.parentNode !== document.body)
            return;

        this._dismissing = true;

        console.assert(this._isListeningForPopoverEvents);
        this._isListeningForPopoverEvents = false;

        window.removeEventListener("mousedown", this, true);
        window.removeEventListener("scroll", this, true);
        window.removeEventListener("resize", this, true);
        window.removeEventListener("keypress", this, true);

        this._prefersDarkColorSchemeMediaQueryList.removeListener(this._boundUpdate);

        WI.quickConsole.keyboardShortcutDisabled = false;

        this._element.classList.add(WI.Popover.FadeOutClassName);

        if (this.delegate && typeof this.delegate.willDismissPopover === "function")
            this.delegate.willDismissPopover(this);
    }

    handleEvent(event)
    {
        switch (event.type) {
        case "mousedown":
        case "scroll":
            if (!this._element.contains(event.target) && !event.target.closest("." + WI.Popover.IgnoreAutoDismissClassName)
                && !event[WI.Popover.EventPreventDismissSymbol]) {
                this.dismiss();
            }
            break;
        case "resize":
            this.resize();
            break;
        case "keypress":
            if (event.keyCode === WI.KeyboardShortcut.Key.Escape.keyCode)
                this.dismiss();
            break;
        case "transitionend":
            if (event.target === this._element) {
                document.body.removeChild(this._element);
                this._element.classList.remove(WI.Popover.FadeOutClassName);
                this._container.textContent = "";
                if (this.delegate && typeof this.delegate.didDismissPopover === "function")
                    this.delegate.didDismissPopover(this);

                this._dismissing = false;
                break;
            }
            break;
        }
    }

    // Private

    _update(shouldAnimate)
    {
        if (shouldAnimate)
            var previousEdge = this._edge;

        var targetFrame = this._targetFrame;
        var preferredEdges = this._preferredEdges;

        // Ensure our element is on display so that its metrics can be resolved
        // or interrupt any pending transition to remove it from display.
        if (this._element.parentNode !== document.body)
            document.body.appendChild(this._element);
        else
            this._element.classList.remove(WI.Popover.FadeOutClassName);

        this._dismissing = false;

        if (this._edge !== null)
            this._element.classList.remove(this._cssClassNameForEdge());

        if (this._contentNeedsUpdate) {
            // Reset CSS properties on element so that the element may be sized to fit its content.
            this._element.style.removeProperty("left");
            this._element.style.removeProperty("top");
            this._element.style.removeProperty("width");
            this._element.style.removeProperty("height");

            // Add the content in place of the wrapper to get the raw metrics.
            this._container.replaceWith(this._content);

            // Get the ideal size for the popover to fit its content.
            var popoverBounds = this._element.getBoundingClientRect();
            this._preferredSize = new WI.Size(Math.ceil(popoverBounds.width), Math.ceil(popoverBounds.height));
        }

        var titleBarOffset = WI.Platform.name === "mac" ? 22 : 0;
        var containerFrame = new WI.Rect(0, titleBarOffset, window.innerWidth, window.innerHeight - titleBarOffset);
        // The frame of the window with a little inset to make sure we have room for shadows.
        containerFrame = containerFrame.inset(WI.Popover.ShadowEdgeInsets);

        // Work out the metrics for all edges.
        var metrics = new Array(preferredEdges.length);
        for (var edgeName in WI.RectEdge) {
            var edge = WI.RectEdge[edgeName];
            var item = {
                edge,
                metrics: this._bestMetricsForEdge(this._preferredSize, targetFrame, containerFrame, edge)
            };
            var preferredIndex = preferredEdges.indexOf(edge);
            if (preferredIndex !== -1)
                metrics[preferredIndex] = item;
            else
                metrics.push(item);
        }

        function area(size)
        {
            return Math.max(0, size.width) * Math.max(0, size.height);
        }

        // Find if any of those fit better than the frame for the preferred edge.
        var bestEdge = metrics[0].edge;
        var bestMetrics = metrics[0].metrics;
        for (var i = 1; i < metrics.length; i++) {
            var itemMetrics = metrics[i].metrics;
            if (area(itemMetrics.contentSize) > area(bestMetrics.contentSize)) {
                bestEdge = metrics[i].edge;
                bestMetrics = itemMetrics;
            }
        }

        console.assert(area(bestMetrics.contentSize) > 0);

        var anchorPoint;
        var bestFrame = bestMetrics.frame.round();

        this._edge = bestEdge;

        if (bestFrame === WI.Rect.ZERO_RECT) {
            // The target for the popover is offscreen.
            this.dismiss();
        } else {
            switch (bestEdge) {
            case WI.RectEdge.MIN_X: // Displayed on the left of the target, arrow points right.
                anchorPoint = new WI.Point(bestFrame.size.width - WI.Popover.ShadowPadding, targetFrame.midY() - bestFrame.minY());
                break;
            case WI.RectEdge.MAX_X: // Displayed on the right of the target, arrow points left.
                anchorPoint = new WI.Point(WI.Popover.ShadowPadding, targetFrame.midY() - bestFrame.minY());
                break;
            case WI.RectEdge.MIN_Y: // Displayed above the target, arrow points down.
                anchorPoint = new WI.Point(targetFrame.midX() - bestFrame.minX(), bestFrame.size.height - WI.Popover.ShadowPadding);
                break;
            case WI.RectEdge.MAX_Y: // Displayed below the target, arrow points up.
                anchorPoint = new WI.Point(targetFrame.midX() - bestFrame.minX(), WI.Popover.ShadowPadding);
                break;
            }

            this._element.classList.add(this._cssClassNameForEdge());

            if (shouldAnimate && this._edge === previousEdge)
                this._animateFrame(bestFrame, anchorPoint);
            else {
                 this.frame = bestFrame;
                 this._setAnchorPoint(anchorPoint);
                 this._drawBackground();
            }

            // Make sure content is centered in case either of the dimension is smaller than the minimal bounds.
            if (this._preferredSize.width < WI.Popover.MinWidth || this._preferredSize.height < WI.Popover.MinHeight)
                this._container.classList.add("center");
            else
                this._container.classList.remove("center");
        }

        // Wrap the content in the container so that it's located correctly.
        if (this._contentNeedsUpdate) {
            this._container.textContent = "";
            this._content.replaceWith(this._container);
            this._container.appendChild(this._content);
        }

        this._contentNeedsUpdate = false;
    }

    _cssClassNameForEdge()
    {
        switch (this._edge) {
        case WI.RectEdge.MIN_X: // Displayed on the left of the target, arrow points right.
            return "arrow-right";
        case WI.RectEdge.MAX_X: // Displayed on the right of the target, arrow points left.
            return "arrow-left";
        case WI.RectEdge.MIN_Y: // Displayed above the target, arrow points down.
            return "arrow-down";
        case WI.RectEdge.MAX_Y: // Displayed below the target, arrow points up.
            return "arrow-up";
        }
        console.error("Unknown edge.");
        return "arrow-up";
    }

    _setAnchorPoint(anchorPoint)
    {
        anchorPoint.x = Math.floor(anchorPoint.x);
        anchorPoint.y = Math.floor(anchorPoint.y);
        this._anchorPoint = anchorPoint;
    }

    _animateFrame(toFrame, toAnchor)
    {
        var startTime = Date.now();
        var duration = 350;
        var epsilon = 1 / (200 * duration);
        var spline = new WI.CubicBezier(0.25, 0.1, 0.25, 1);

        var fromFrame = this._frame.copy();
        var fromAnchor = this._anchorPoint.copy();

        function animatedValue(from, to, progress)
        {
            return from + (to - from) * progress;
        }

        function drawBackground()
        {
            var progress = spline.solve(Math.min((Date.now() - startTime) / duration, 1), epsilon);

            this.frame = new WI.Rect(
                animatedValue(fromFrame.minX(), toFrame.minX(), progress),
                animatedValue(fromFrame.minY(), toFrame.minY(), progress),
                animatedValue(fromFrame.size.width, toFrame.size.width, progress),
                animatedValue(fromFrame.size.height, toFrame.size.height, progress)
            ).round();

            this._setAnchorPoint(new WI.Point(
                animatedValue(fromAnchor.x, toAnchor.x, progress),
                animatedValue(fromAnchor.y, toAnchor.y, progress)
            ));

            this._drawBackground();

            if (progress < 1)
                this._drawBackgroundAnimationIdentifier = requestAnimationFrame(drawBackground.bind(this));
        }

        drawBackground.call(this);
    }

    _drawBackground()
    {
        if (this._drawBackgroundAnimationIdentifier) {
            cancelAnimationFrame(this._drawBackgroundAnimationIdentifier);
            this._drawBackgroundAnimationIdentifier = undefined;
        }

        let scaleFactor = window.devicePixelRatio;

        let width = this._frame.size.width;
        let height = this._frame.size.height;
        let scaledWidth = width * scaleFactor;
        let scaledHeight = height * scaleFactor;

        // Bounds of the path don't take into account the arrow, but really only the tight bounding box
        // of the content contained within the frame.
        let bounds;
        switch (this._edge) {
        case WI.RectEdge.MIN_X: // Displayed on the left of the target, arrow points right.
            bounds = new WI.Rect(0, 0, width - WI.Popover.AnchorSize, height);
            break;
        case WI.RectEdge.MAX_X: // Displayed on the right of the target, arrow points left.
            bounds = new WI.Rect(WI.Popover.AnchorSize, 0, width - WI.Popover.AnchorSize, height);
            break;
        case WI.RectEdge.MIN_Y: // Displayed above the target, arrow points down.
            bounds = new WI.Rect(0, 0, width, height - WI.Popover.AnchorSize);
            break;
        case WI.RectEdge.MAX_Y: // Displayed below the target, arrow points up.
            bounds = new WI.Rect(0, WI.Popover.AnchorSize, width, height - WI.Popover.AnchorSize);
            break;
        }

        bounds = bounds.inset(WI.Popover.ShadowEdgeInsets);
        let computedStyle = window.getComputedStyle(this._element, null);

        let context = document.getCSSCanvasContext("2d", "popover", scaledWidth, scaledHeight);
        context.clearRect(0, 0, scaledWidth, scaledHeight);

        function isolate(callback) {
            context.save();
            callback();
            context.restore();
        }

        isolate(() => {
            context.scale(scaleFactor, scaleFactor);
            this._drawFrame(context, bounds, this._edge, this._anchorPoint);

            isolate(() => {
                context.shadowBlur = 4;
                context.shadowColor = computedStyle.getPropertyValue("--popover-shadow-color").trim();

                context.strokeStyle = computedStyle.getPropertyValue("--popover-border-color").trim();
                context.lineWidth = 2;
                context.stroke();
            });

            isolate(() => {
                context.fillStyle = computedStyle.getPropertyValue("--popover-background-color").trim();
                context.fill();
            });
        });
    }

    _bestMetricsForEdge(preferredSize, targetFrame, containerFrame, edge)
    {
        var x, y;
        var width = preferredSize.width + (WI.Popover.ShadowPadding * 2) + (WI.Popover.ContentPadding * 2);
        var height = preferredSize.height + (WI.Popover.ShadowPadding * 2) + (WI.Popover.ContentPadding * 2);

        switch (edge) {
        case WI.RectEdge.MIN_X: // Displayed on the left of the target, arrow points right.
            width += WI.Popover.AnchorSize;
            x = targetFrame.origin.x - width + WI.Popover.ShadowPadding;
            y = targetFrame.origin.y - (height - targetFrame.size.height) / 2;
            break;
        case WI.RectEdge.MAX_X: // Displayed on the right of the target, arrow points left.
            width += WI.Popover.AnchorSize;
            x = targetFrame.origin.x + targetFrame.size.width - WI.Popover.ShadowPadding;
            y = targetFrame.origin.y - (height - targetFrame.size.height) / 2;
            break;
        case WI.RectEdge.MIN_Y: // Displayed above the target, arrow points down.
            height += WI.Popover.AnchorSize;
            x = targetFrame.origin.x - (width - targetFrame.size.width) / 2;
            y = targetFrame.origin.y - height + WI.Popover.ShadowPadding;
            break;
        case WI.RectEdge.MAX_Y: // Displayed below the target, arrow points up.
            height += WI.Popover.AnchorSize;
            x = targetFrame.origin.x - (width - targetFrame.size.width) / 2;
            y = targetFrame.origin.y + targetFrame.size.height - WI.Popover.ShadowPadding;
            break;
        }

        if (edge !== WI.RectEdge.MIN_X && x < containerFrame.minX())
            x = containerFrame.minX();
        if (edge !== WI.RectEdge.MAX_X && x + width > containerFrame.maxX())
            x = containerFrame.maxX() - width;
        if (edge !== WI.RectEdge.MIN_Y && y < containerFrame.minY())
            y = containerFrame.minY();
        if (edge !== WI.RectEdge.MAX_Y && y + height > containerFrame.maxY())
            y = containerFrame.maxY() - height;

        var preferredFrame = new WI.Rect(x, y, width, height);
        var bestFrame = preferredFrame.intersectionWithRect(containerFrame);

        width = bestFrame.size.width - (WI.Popover.ShadowPadding * 2);
        height = bestFrame.size.height - (WI.Popover.ShadowPadding * 2);

        switch (edge) {
        case WI.RectEdge.MIN_X: // Displayed on the left of the target, arrow points right.
        case WI.RectEdge.MAX_X: // Displayed on the right of the target, arrow points left.
            width -= WI.Popover.AnchorSize;
            break;
        case WI.RectEdge.MIN_Y: // Displayed above the target, arrow points down.
        case WI.RectEdge.MAX_Y: // Displayed below the target, arrow points up.
            height -= WI.Popover.AnchorSize;
            break;
        }

        return {
            frame: bestFrame,
            contentSize: new WI.Size(width, height)
        };
    }

    _drawFrame(ctx, bounds, anchorEdge)
    {
        let cornerRadius = WI.Popover.CornerRadius;
        let anchorPoint = this._anchorPoint;

        // Prevent the arrow from being positioned against one of the popover's rounded corners.
        let arrowPadding = cornerRadius + WI.Popover.AnchorSize;
        if (anchorEdge === WI.RectEdge.MIN_Y || anchorEdge === WI.RectEdge.MAX_Y)
            anchorPoint.x = Number.constrain(anchorPoint.x, bounds.minX() + arrowPadding, bounds.maxX() - arrowPadding);
        else
            anchorPoint.y = Number.constrain(anchorPoint.y, bounds.minY() + arrowPadding, bounds.maxY() - arrowPadding);

        ctx.beginPath();
        switch (anchorEdge) {
        case WI.RectEdge.MIN_X: // Displayed on the left of the target, arrow points right.
            ctx.moveTo(bounds.maxX(), bounds.minY() + cornerRadius);
            ctx.lineTo(bounds.maxX(), anchorPoint.y - WI.Popover.AnchorSize);
            ctx.lineTo(anchorPoint.x, anchorPoint.y);
            ctx.lineTo(bounds.maxX(), anchorPoint.y + WI.Popover.AnchorSize);
            ctx.arcTo(bounds.maxX(), bounds.maxY(), bounds.minX(), bounds.maxY(), cornerRadius);
            ctx.arcTo(bounds.minX(), bounds.maxY(), bounds.minX(), bounds.minY(), cornerRadius);
            ctx.arcTo(bounds.minX(), bounds.minY(), bounds.maxX(), bounds.minY(), cornerRadius);
            ctx.arcTo(bounds.maxX(), bounds.minY(), bounds.maxX(), bounds.maxY(), cornerRadius);
            break;
        case WI.RectEdge.MAX_X: // Displayed on the right of the target, arrow points left.
            ctx.moveTo(bounds.minX(), bounds.maxY() - cornerRadius);
            ctx.lineTo(bounds.minX(), anchorPoint.y + WI.Popover.AnchorSize);
            ctx.lineTo(anchorPoint.x, anchorPoint.y);
            ctx.lineTo(bounds.minX(), anchorPoint.y - WI.Popover.AnchorSize);
            ctx.arcTo(bounds.minX(), bounds.minY(), bounds.maxX(), bounds.minY(), cornerRadius);
            ctx.arcTo(bounds.maxX(), bounds.minY(), bounds.maxX(), bounds.maxY(), cornerRadius);
            ctx.arcTo(bounds.maxX(), bounds.maxY(), bounds.minX(), bounds.maxY(), cornerRadius);
            ctx.arcTo(bounds.minX(), bounds.maxY(), bounds.minX(), bounds.minY(), cornerRadius);
            break;
        case WI.RectEdge.MIN_Y: // Displayed above the target, arrow points down.
            ctx.moveTo(bounds.maxX() - cornerRadius, bounds.maxY());
            ctx.lineTo(anchorPoint.x + WI.Popover.AnchorSize, bounds.maxY());
            ctx.lineTo(anchorPoint.x, anchorPoint.y);
            ctx.lineTo(anchorPoint.x - WI.Popover.AnchorSize, bounds.maxY());
            ctx.arcTo(bounds.minX(), bounds.maxY(), bounds.minX(), bounds.minY(), cornerRadius);
            ctx.arcTo(bounds.minX(), bounds.minY(), bounds.maxX(), bounds.minY(), cornerRadius);
            ctx.arcTo(bounds.maxX(), bounds.minY(), bounds.maxX(), bounds.maxY(), cornerRadius);
            ctx.arcTo(bounds.maxX(), bounds.maxY(), bounds.minX(), bounds.maxY(), cornerRadius);
            break;
        case WI.RectEdge.MAX_Y: // Displayed below the target, arrow points up.
            ctx.moveTo(bounds.minX() + cornerRadius, bounds.minY());
            ctx.lineTo(anchorPoint.x - WI.Popover.AnchorSize, bounds.minY());
            ctx.lineTo(anchorPoint.x, anchorPoint.y);
            ctx.lineTo(anchorPoint.x + WI.Popover.AnchorSize, bounds.minY());
            ctx.arcTo(bounds.maxX(), bounds.minY(), bounds.maxX(), bounds.maxY(), cornerRadius);
            ctx.arcTo(bounds.maxX(), bounds.maxY(), bounds.minX(), bounds.maxY(), cornerRadius);
            ctx.arcTo(bounds.minX(), bounds.maxY(), bounds.minX(), bounds.minY(), cornerRadius);
            ctx.arcTo(bounds.minX(), bounds.minY(), bounds.maxX(), bounds.minY(), cornerRadius);
            break;
        }
        ctx.closePath();
    }

    _addListenersIfNeeded()
    {
        if (!this._isListeningForPopoverEvents) {
            this._isListeningForPopoverEvents = true;

            window.addEventListener("mousedown", this, true);
            window.addEventListener("scroll", this, true);
            window.addEventListener("resize", this, true);
            window.addEventListener("keypress", this, true);

            if (!this._boundUpdate)
                this._boundUpdate = this._update.bind(this);

            if (!this._prefersDarkColorSchemeMediaQueryList)
                this._prefersDarkColorSchemeMediaQueryList = window.matchMedia("(prefers-color-scheme: dark)");
            this._prefersDarkColorSchemeMediaQueryList.addListener(this._boundUpdate);

            WI.quickConsole.keyboardShortcutDisabled = true;
        }
    }
};

WI.Popover.FadeOutClassName = "fade-out";
WI.Popover.CornerRadius = 5;
WI.Popover.MinWidth = 40;
WI.Popover.MinHeight = 40;
WI.Popover.ShadowPadding = 5;
WI.Popover.ContentPadding = 5;
WI.Popover.AnchorSize = 11;
WI.Popover.ShadowEdgeInsets = new WI.EdgeInsets(WI.Popover.ShadowPadding);
WI.Popover.IgnoreAutoDismissClassName = "popover-ignore-auto-dismiss";
WI.Popover.EventPreventDismissSymbol = Symbol("popover-event-prevent-dismiss");
