/*
 * Copyright (C) 2013 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.
 */

WebInspector.Popover = function(delegate) {
    // FIXME: Convert this to a WebInspector.Object subclass, and call super().
    // WebInspector.Object.call(this);

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

    this._contentNeedsUpdate = false;

    this._element = document.createElement("div");
    this._element.className = WebInspector.Popover.StyleClassName;
    this._canvasId = "popover-" + (WebInspector.Popover.canvasId++);
    this._element.style.backgroundImage = "-webkit-canvas(" + this._canvasId + ")";
    this._element.addEventListener("transitionend", this, true);

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

WebInspector.Popover.StyleClassName = "popover";
WebInspector.Popover.FadeOutClassName = "fade-out";
WebInspector.Popover.canvasId = 0;
WebInspector.Popover.CornerRadius = 5;
WebInspector.Popover.MinWidth = 40;
WebInspector.Popover.MinHeight = 40;
WebInspector.Popover.ShadowPadding = 5;
WebInspector.Popover.ContentPadding = 5;
WebInspector.Popover.AnchorSize = new WebInspector.Size(22, 11);
WebInspector.Popover.ShadowEdgeInsets = new WebInspector.EdgeInsets(WebInspector.Popover.ShadowPadding);

WebInspector.Popover.prototype = {
    constructor: WebInspector.Popover,

    // Public

    get element()
    {
        return this._element;
    },

    get frame()
    {
        return this._frame;
    },

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

    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);
    },

    update: function()
    {
        if (!this.visible)
            return;

        var previouslyFocusedElement = document.activeElement;

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

        if (previouslyFocusedElement)
            previouslyFocusedElement.focus();
    },

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

        if (!this._content)
            return;

        this._addListenersIfNeeded();

        this._update();
    },

    presentNewContentWithFrame: function(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: function()
    {
        if (this._element.parentNode !== document.body)
            return;

        console.assert(this._isListeningForPopoverEvents);
        this._isListeningForPopoverEvents = false;
        window.removeEventListener("mousedown", this, true);
        window.removeEventListener("scroll", this, true);

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

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

    handleEvent: function(event)
    {
        switch (event.type) {
        case "mousedown":
        case "scroll":
            if (!this._element.contains(event.target))
                this.dismiss();
            break;
        case "transitionend":
            if (event.target === this._element) {
                document.body.removeChild(this._element);
                this._element.classList.remove(WebInspector.Popover.FadeOutClassName);
                this._container.textContent = "";
                if (this.delegate && typeof this.delegate.didDismissPopover === "function")
                    this.delegate.didDismissPopover(this);
                break;
            }
        }
    },

    // Private

    _update: function(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(WebInspector.Popover.FadeOutClassName);

        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");
            if (this._edge !== null)
                this._element.classList.remove(this._cssClassNameForEdge());

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

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

        const titleBarOffset = WebInspector.Platform.name === "mac" && !WebInspector.Platform.isLegacyMacOS ? 22 : 0;
        var containerFrame = new WebInspector.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(WebInspector.Popover.ShadowEdgeInsets);

        // Work out the metrics for all edges.
        var metrics = new Array(preferredEdges.length);
        for (var edgeName in WebInspector.RectEdge) {
            var edge = WebInspector.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 size.width * 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;
            }
        }

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

        this._edge = bestEdge;

        if (bestFrame === WebInspector.Rect.ZERO_RECT) {
            // The target for the popover is offscreen.
            this.dismiss();
        } else {
            switch (bestEdge) {
            case WebInspector.RectEdge.MIN_X: // Displayed on the left of the target, arrow points right.
                anchorPoint = new WebInspector.Point(bestFrame.size.width - WebInspector.Popover.ShadowPadding, targetFrame.midY() - bestFrame.minY());
                break;
            case WebInspector.RectEdge.MAX_X: // Displayed on the right of the target, arrow points left.
                anchorPoint = new WebInspector.Point(WebInspector.Popover.ShadowPadding, targetFrame.midY() - bestFrame.minY());
                break;
            case WebInspector.RectEdge.MIN_Y: // Displayed above the target, arrow points down.
                anchorPoint = new WebInspector.Point(targetFrame.midX() - bestFrame.minX(), bestFrame.size.height - WebInspector.Popover.ShadowPadding);
                break;
            case WebInspector.RectEdge.MAX_Y: // Displayed below the target, arrow points up.
                anchorPoint = new WebInspector.Point(targetFrame.midX() - bestFrame.minX(), WebInspector.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 < WebInspector.Popover.MinWidth || this._preferredSize.height < WebInspector.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._element.replaceChild(this._container, this._content);
            this._container.appendChild(this._content);
        }

        this._contentNeedsUpdate = false;
    },

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

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

    _animateFrame: function(toFrame, toAnchor)
    {
        var startTime = Date.now();
        var duration = 350;
        var epsilon = 1 / (200 * duration);
        var spline = new WebInspector.UnitBezier(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 WebInspector.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 WebInspector.Point(
                animatedValue(fromAnchor.x, toAnchor.x, progress),
                animatedValue(fromAnchor.y, toAnchor.y, progress)
            ));

            this._drawBackground();

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

        drawBackground.call(this);
    },

    _drawBackground: function()
    {
        var scaleFactor = window.devicePixelRatio;

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

        // Create a scratch canvas so we can draw the popover that will later be drawn into
        // the final context with a shadow.
        var scratchCanvas = document.createElement("canvas");
        scratchCanvas.width = scaledWidth;
        scratchCanvas.height = scaledHeight;

        var ctx = scratchCanvas.getContext("2d");
        ctx.scale(scaleFactor, 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.
        var bounds;
        var arrowHeight = WebInspector.Popover.AnchorSize.height;
        switch (this._edge) {
        case WebInspector.RectEdge.MIN_X: // Displayed on the left of the target, arrow points right.
            bounds = new WebInspector.Rect(0, 0, width - arrowHeight, height);
            break;
        case WebInspector.RectEdge.MAX_X: // Displayed on the right of the target, arrow points left.
            bounds = new WebInspector.Rect(arrowHeight, 0, width - arrowHeight, height);
            break;
        case WebInspector.RectEdge.MIN_Y: // Displayed above the target, arrow points down.
            bounds = new WebInspector.Rect(0, 0, width, height - arrowHeight);
            break;
        case WebInspector.RectEdge.MAX_Y: // Displayed below the target, arrow points up.
            bounds = new WebInspector.Rect(0, arrowHeight, width, height - arrowHeight);
            break;
        }

        bounds = bounds.inset(WebInspector.Popover.ShadowEdgeInsets);

        // Clip the frame.
        ctx.fillStyle = "black";
        this._drawFrame(ctx, bounds, this._edge, this._anchorPoint);
        ctx.clip();

        // Gradient fill, top-to-bottom.
        var fillGradient = ctx.createLinearGradient(0, 0, 0, height);
        fillGradient.addColorStop(0, "rgba(255, 255, 255, 0.95)");
        fillGradient.addColorStop(1, "rgba(235, 235, 235, 0.95)");
        ctx.fillStyle = fillGradient;
        ctx.fillRect(0, 0, width, height);

        // Stroke.
        ctx.strokeStyle = "rgba(0, 0, 0, 0.25)";
        ctx.lineWidth = 2;
        this._drawFrame(ctx, bounds, this._edge, this._anchorPoint);
        ctx.stroke();

        // Draw the popover into the final context with a drop shadow.
        var finalContext = document.getCSSCanvasContext("2d", this._canvasId, scaledWidth, scaledHeight);

        finalContext.clearRect(0, 0, scaledWidth, scaledHeight);

        finalContext.shadowOffsetX = 1;
        finalContext.shadowOffsetY = 1;
        finalContext.shadowBlur = 5;
        finalContext.shadowColor = "rgba(0, 0, 0, 0.5)";

        finalContext.drawImage(scratchCanvas, 0, 0, scaledWidth, scaledHeight);
    },

    _bestMetricsForEdge: function(preferredSize, targetFrame, containerFrame, edge)
    {
        var x, y;
        var width = preferredSize.width + (WebInspector.Popover.ShadowPadding * 2) + (WebInspector.Popover.ContentPadding * 2);
        var height = preferredSize.height + (WebInspector.Popover.ShadowPadding * 2) + (WebInspector.Popover.ContentPadding * 2);
        var arrowLength = WebInspector.Popover.AnchorSize.height;

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

        if (edge === WebInspector.RectEdge.MIN_X || edge === WebInspector.RectEdge.MAX_X) {
            if (y < containerFrame.minY())
                y = containerFrame.minY();
            if (y + height > containerFrame.maxY())
                y = containerFrame.maxY() - height;
        } else {
            if (x < containerFrame.minX())
                x = containerFrame.minX();
            if (x + width > containerFrame.maxX())
                x = containerFrame.maxX() - width;
        }

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

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

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

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

    _drawFrame: function(ctx, bounds, anchorEdge)
    {
        var r = WebInspector.Popover.CornerRadius;
        var arrowHalfLength = WebInspector.Popover.AnchorSize.width / 2;
        var anchorPoint = this._anchorPoint;

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

    _addListenersIfNeeded: function()
    {
        if (!this._isListeningForPopoverEvents) {
            this._isListeningForPopoverEvents = true;
            window.addEventListener("mousedown", this, true);
            window.addEventListener("scroll", this, true);
        }
    }
};

WebInspector.Popover.prototype.__proto__ = WebInspector.Object.prototype;
