/*
 * 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.undockedTitleAreaHeight();
        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");
