/*
 * Copyright (C) 2013 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.CanvasProfileHeader} profile
 */
WebInspector.CanvasProfileView = function(profile)
{
    WebInspector.View.call(this);
    this.registerRequiredCSS("canvasProfiler.css");
    this.element.addStyleClass("canvas-profile-view");
    this._profile = profile;
    this._traceLogId = profile.traceLogId();
    this._traceLogPlayer = profile.traceLogPlayer();
    this._linkifier = new WebInspector.Linkifier();

    const defaultReplayLogWidthPercent = 0.34;
    this._replayInfoSplitView = new WebInspector.SplitView(true, "canvasProfileViewReplaySplitLocation", defaultReplayLogWidthPercent);
    this._replayInfoSplitView.setMainElementConstraints(defaultReplayLogWidthPercent, defaultReplayLogWidthPercent);
    this._replayInfoSplitView.show(this.element);

    this._imageSplitView = new WebInspector.SplitView(false, "canvasProfileViewSplitLocation", 300);
    this._imageSplitView.show(this._replayInfoSplitView.firstElement());

    var replayImageContainer = this._imageSplitView.firstElement();
    replayImageContainer.id = "canvas-replay-image-container";
    this._replayImageElement = replayImageContainer.createChild("image", "canvas-replay-image");
    this._debugInfoElement = replayImageContainer.createChild("div", "canvas-debug-info hidden");
    this._spinnerIcon = replayImageContainer.createChild("img", "canvas-spinner-icon hidden");

    var replayLogContainer = this._imageSplitView.secondElement();
    var controlsContainer = replayLogContainer.createChild("div", "status-bar");
    var logGridContainer = replayLogContainer.createChild("div", "canvas-replay-log");

    this._createControlButton(controlsContainer, "canvas-replay-first-step", WebInspector.UIString("First call."), this._onReplayFirstStepClick.bind(this));
    this._createControlButton(controlsContainer, "canvas-replay-prev-step", WebInspector.UIString("Previous call."), this._onReplayStepClick.bind(this, false));
    this._createControlButton(controlsContainer, "canvas-replay-next-step", WebInspector.UIString("Next call."), this._onReplayStepClick.bind(this, true));
    this._createControlButton(controlsContainer, "canvas-replay-prev-draw", WebInspector.UIString("Previous drawing call."), this._onReplayDrawingCallClick.bind(this, false));
    this._createControlButton(controlsContainer, "canvas-replay-next-draw", WebInspector.UIString("Next drawing call."), this._onReplayDrawingCallClick.bind(this, true));
    this._createControlButton(controlsContainer, "canvas-replay-last-step", WebInspector.UIString("Last call."), this._onReplayLastStepClick.bind(this));

    this._replayContextSelector = new WebInspector.StatusBarComboBox(this._onReplayContextChanged.bind(this));
    this._replayContextSelector.createOption(WebInspector.UIString("<screenshot auto>"), WebInspector.UIString("Show screenshot of the last replayed resource."), "");
    controlsContainer.appendChild(this._replayContextSelector.element);

    this._installReplayInfoSidebarWidgets(controlsContainer);

    this._replayStateView = new WebInspector.CanvasReplayStateView(this._traceLogPlayer);
    this._replayStateView.show(this._replayInfoSplitView.secondElement());

    /** @type {!Object.<string, boolean>} */
    this._replayContexts = {};

    var columns = [
        {title: "#", sortable: false, width: "5%"},
        {title: WebInspector.UIString("Call"), sortable: false, width: "75%", disclosure: true},
        {title: WebInspector.UIString("Location"), sortable: false, width: "20%"}
    ];

    this._logGrid = new WebInspector.DataGrid(columns);
    this._logGrid.element.addStyleClass("fill");
    this._logGrid.show(logGridContainer);
    this._logGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, this._replayTraceLog, this);

    this.element.addEventListener("mousedown", this._onMouseClick.bind(this), true);

    this._popoverHelper = new WebInspector.ObjectPopoverHelper(this.element, this._popoverAnchor.bind(this), this._resolveObjectForPopover.bind(this), this._onHidePopover.bind(this), true);
    this._popoverHelper.setRemoteObjectFormatter(this._hexNumbersFormatter.bind(this));

    this._requestTraceLog(0);
}

/**
 * @const
 * @type {number}
 */
WebInspector.CanvasProfileView.TraceLogPollingInterval = 500;

WebInspector.CanvasProfileView.prototype = {
    dispose: function()
    {
        this._linkifier.reset();
    },

    get statusBarItems()
    {
        return [];
    },

    get profile()
    {
        return this._profile;
    },

    /**
     * @override
     * @return {Array.<Element>}
     */
    elementsToRestoreScrollPositionsFor: function()
    {
        return [this._logGrid.scrollContainer];
    },

    /**
     * @param {!Element} controlsContainer
     */
    _installReplayInfoSidebarWidgets: function(controlsContainer)
    {
        this._replayInfoResizeWidgetElement = controlsContainer.createChild("div", "resizer-widget");
        this._replayInfoSplitView.installResizer(this._replayInfoResizeWidgetElement);

        this._toggleReplayStateSidebarButton = new WebInspector.StatusBarButton("", "right-sidebar-show-hide-button canvas-sidebar-show-hide-button", 3);
        this._toggleReplayStateSidebarButton.addEventListener("click", clickHandler, this);
        controlsContainer.appendChild(this._toggleReplayStateSidebarButton.element);
        this._enableReplayInfoSidebar(false);

        function clickHandler()
        {
            this._enableReplayInfoSidebar(this._toggleReplayStateSidebarButton.state === "left");
        }
    },

    /**
     * @param {boolean} show
     */
    _enableReplayInfoSidebar: function(show)
    {
        if (show) {
            this._toggleReplayStateSidebarButton.state = "right";
            this._toggleReplayStateSidebarButton.title = WebInspector.UIString("Hide sidebar.");
            this._replayInfoSplitView.showBoth();
        } else {
            this._toggleReplayStateSidebarButton.state = "left";
            this._toggleReplayStateSidebarButton.title = WebInspector.UIString("Show sidebar.");
            this._replayInfoSplitView.showOnlyFirst();
        }
        this._replayInfoResizeWidgetElement.enableStyleClass("hidden", !show);
    },

    /**
     * @param {Event} event
     */
    _onMouseClick: function(event)
    {
        var resourceLinkElement = event.target.enclosingNodeOrSelfWithClass("canvas-formatted-resource");
        if (resourceLinkElement) {
            this._enableReplayInfoSidebar(true);
            this._replayStateView.selectResource(resourceLinkElement.__resourceId);
            event.consume(true);
            return;
        }
        if (event.target.enclosingNodeOrSelfWithClass("webkit-html-resource-link"))
            event.consume(false);
    },

    /**
     * @param {Element} parent
     * @param {string} className
     * @param {string} title
     * @param {function(this:WebInspector.CanvasProfileView)} clickCallback
     */
    _createControlButton: function(parent, className, title, clickCallback)
    {
        var button = new WebInspector.StatusBarButton(title, className + " canvas-replay-button");
        parent.appendChild(button.element);

        button.makeLongClickEnabled();
        button.addEventListener("click", clickCallback, this);
        button.addEventListener("longClickDown", clickCallback, this);
        button.addEventListener("longClickPress", clickCallback, this);
    },

    _onReplayContextChanged: function()
    {
        var selectedContextId = this._replayContextSelector.selectedOption().value;

        /**
         * @param {?CanvasAgent.ResourceState} resourceState
         */
        function didReceiveResourceState(resourceState)
        {
            this._enableWaitIcon(false);
            if (selectedContextId !== this._replayContextSelector.selectedOption().value)
                return;
            var imageURL = (resourceState && resourceState.imageURL) || "";
            this._replayImageElement.src = imageURL;
            this._replayImageElement.style.visibility = imageURL ? "" : "hidden";
        }

        this._enableWaitIcon(true);
        this._traceLogPlayer.getResourceState(selectedContextId, didReceiveResourceState.bind(this));
    },

    /**
     * @param {boolean} forward
     */
    _onReplayStepClick: function(forward)
    {
        var selectedNode = this._logGrid.selectedNode;
        if (!selectedNode)
            return;
        var nextNode = selectedNode;
        do {
            nextNode = forward ? nextNode.traverseNextNode(false) : nextNode.traversePreviousNode(false);
        } while (nextNode && typeof nextNode.index !== "number");
        (nextNode || selectedNode).revealAndSelect();
    },

    /**
     * @param {boolean} forward
     */
    _onReplayDrawingCallClick: function(forward)
    {
        var selectedNode = this._logGrid.selectedNode;
        if (!selectedNode)
            return;
        var nextNode = selectedNode;
        while (nextNode) {
            var sibling = forward ? nextNode.nextSibling : nextNode.previousSibling;
            if (sibling) {
                nextNode = sibling;
                if (nextNode.hasChildren || nextNode.call.isDrawingCall)
                    break;
            } else {
                nextNode = nextNode.parent;
                if (!forward)
                    break;
            }
        }
        if (!nextNode && forward)
            this._onReplayLastStepClick();
        else
            (nextNode || selectedNode).revealAndSelect();
    },

    _onReplayFirstStepClick: function()
    {
        var firstNode = this._logGrid.rootNode().children[0];
        if (firstNode)
            firstNode.revealAndSelect();
    },

    _onReplayLastStepClick: function()
    {
        var lastNode = this._logGrid.rootNode().children.peekLast();
        if (!lastNode)
            return;
        while (lastNode.expanded) {
            var lastChild = lastNode.children.peekLast();
            if (!lastChild)
                break;
            lastNode = lastChild;
        }
        lastNode.revealAndSelect();
    },

    /**
     * @param {boolean} enable
     */
    _enableWaitIcon: function(enable)
    {
        this._spinnerIcon.enableStyleClass("hidden", !enable);
        this._debugInfoElement.enableStyleClass("hidden", enable);
    },

    _replayTraceLog: function()
    {
        if (this._pendingReplayTraceLogEvent)
            return;
        var index = this._selectedCallIndex();
        if (index === -1 || index === this._lastReplayCallIndex)
            return;
        this._lastReplayCallIndex = index;
        this._pendingReplayTraceLogEvent = true;
        /**
         * @param {CanvasAgent.ResourceState} resourceState
         * @param {number} replayTime
         */
        function didReplayTraceLog(resourceState, replayTime)
        {
            delete this._pendingReplayTraceLogEvent;
            this._enableWaitIcon(false);

            this._debugInfoElement.textContent = "Replay time: " + Number.secondsToString(replayTime / 1000, true);
            this._onReplayContextChanged();

            if (index !== this._selectedCallIndex())
                this._replayTraceLog();
        }
        this._enableWaitIcon(true);
        this._traceLogPlayer.replayTraceLog(index, didReplayTraceLog.bind(this));
    },

    /**
     * @param {number} offset
     */
    _requestTraceLog: function(offset)
    {
        /**
         * @param {?CanvasAgent.TraceLog} traceLog
         */
        function didReceiveTraceLog(traceLog)
        {
            this._enableWaitIcon(false);
            if (!traceLog)
                return;
            var callNodes = [];
            var calls = traceLog.calls;
            var index = traceLog.startOffset;
            for (var i = 0, n = calls.length; i < n; ++i)
                callNodes.push(this._createCallNode(index++, calls[i]));
            var contexts = traceLog.contexts;
            for (var i = 0, n = contexts.length; i < n; ++i) {
                var contextId = contexts[i].resourceId || "";
                var description = contexts[i].description || "";
                if (this._replayContexts[contextId])
                    continue;
                this._replayContexts[contextId] = true;
                this._replayContextSelector.createOption(description, WebInspector.UIString("Show screenshot of this context's canvas."), contextId);
            }
            this._appendCallNodes(callNodes);
            if (traceLog.alive)
                setTimeout(this._requestTraceLog.bind(this, index), WebInspector.CanvasProfileView.TraceLogPollingInterval);
            else
                this._flattenSingleFrameNode();
            this._profile._updateCapturingStatus(traceLog);
            this._onReplayLastStepClick(); // Automatically replay the last step.
        }
        this._enableWaitIcon(true);
        this._traceLogPlayer.getTraceLog(offset, undefined, didReceiveTraceLog.bind(this));
    },

    /**
     * @return {number}
     */
    _selectedCallIndex: function()
    {
        var node = this._logGrid.selectedNode;
        return node ? this._peekLastRecursively(node).index : -1;
    },

    /**
     * @param {!WebInspector.DataGridNode} node
     * @return {!WebInspector.DataGridNode}
     */
    _peekLastRecursively: function(node)
    {
        var lastChild;
        while ((lastChild = node.children.peekLast()))
            node = lastChild;
        return node;
    },

    /**
     * @param {!Array.<!WebInspector.DataGridNode>} callNodes
     */
    _appendCallNodes: function(callNodes)
    {
        var rootNode = this._logGrid.rootNode();
        var frameNode = rootNode.children.peekLast();
        if (frameNode && this._peekLastRecursively(frameNode).call.isFrameEndCall)
            frameNode = null;
        for (var i = 0, n = callNodes.length; i < n; ++i) {
            if (!frameNode) {
                var index = rootNode.children.length;
                var data = {};
                data[0] = "";
                data[1] = "Frame #" + (index + 1);
                data[2] = "";
                frameNode = new WebInspector.DataGridNode(data);
                frameNode.selectable = true;
                rootNode.appendChild(frameNode);
            }
            var nextFrameCallIndex = i + 1;
            while (nextFrameCallIndex < n && !callNodes[nextFrameCallIndex - 1].call.isFrameEndCall)
                ++nextFrameCallIndex;
            this._appendCallNodesToFrameNode(frameNode, callNodes, i, nextFrameCallIndex);
            i = nextFrameCallIndex - 1;
            frameNode = null;
        }
    },

    /**
     * @param {!WebInspector.DataGridNode} frameNode
     * @param {!Array.<!WebInspector.DataGridNode>} callNodes
     * @param {number} fromIndex
     * @param {number} toIndex not inclusive
     */
    _appendCallNodesToFrameNode: function(frameNode, callNodes, fromIndex, toIndex)
    {
        var self = this;
        function appendDrawCallGroup()
        {
            var index = self._drawCallGroupsCount || 0;
            var data = {};
            data[0] = "";
            data[1] = "Draw call group #" + (index + 1);
            data[2] = "";
            var node = new WebInspector.DataGridNode(data);
            node.selectable = true;
            self._drawCallGroupsCount = index + 1;
            frameNode.appendChild(node);
            return node;
        }

        function splitDrawCallGroup(drawCallGroup)
        {
            var splitIndex = 0;
            var splitNode;
            while ((splitNode = drawCallGroup.children[splitIndex])) {
                if (splitNode.call.isDrawingCall)
                    break;
                ++splitIndex;
            }
            var newDrawCallGroup = appendDrawCallGroup();
            var lastNode;
            while ((lastNode = drawCallGroup.children[splitIndex + 1]))
                newDrawCallGroup.appendChild(lastNode);
            return newDrawCallGroup;
        }

        var drawCallGroup = frameNode.children.peekLast();
        var groupHasDrawCall = false;
        if (drawCallGroup) {
            for (var i = 0, n = drawCallGroup.children.length; i < n; ++i) {
                if (drawCallGroup.children[i].call.isDrawingCall) {
                    groupHasDrawCall = true;
                    break;
                }
            }
        } else
            drawCallGroup = appendDrawCallGroup();

        for (var i = fromIndex; i < toIndex; ++i) {
            var node = callNodes[i];
            drawCallGroup.appendChild(node);
            if (node.call.isDrawingCall) {
                if (groupHasDrawCall)
                    drawCallGroup = splitDrawCallGroup(drawCallGroup);
                else
                    groupHasDrawCall = true;
            }
        }
    },

    /**
     * @param {number} index
     * @param {CanvasAgent.Call} call
     * @return {!WebInspector.DataGridNode}
     */
    _createCallNode: function(index, call)
    {
        var callViewElement = document.createElement("div");

        var data = {};
        data[0] = index + 1;
        data[1] = callViewElement;
        data[2] = "";
        if (call.sourceURL) {
            // FIXME(62725): stack trace line/column numbers are one-based.
            var lineNumber = Math.max(0, call.lineNumber - 1) || 0;
            var columnNumber = Math.max(0, call.columnNumber - 1) || 0;
            data[2] = this._linkifier.linkifyLocation(call.sourceURL, lineNumber, columnNumber);
        }

        callViewElement.createChild("span", "canvas-function-name").textContent = call.functionName || "context." + call.property;

        if (call.arguments) {
            callViewElement.createTextChild("(");
            for (var i = 0, n = call.arguments.length; i < n; ++i) {
                var argument = /** @type {!CanvasAgent.CallArgument} */ (call.arguments[i]);
                if (i)
                    callViewElement.createTextChild(", ");
                var element = WebInspector.CanvasProfileDataGridHelper.createCallArgumentElement(argument);
                element.__argumentIndex = i;
                callViewElement.appendChild(element);
            }
            callViewElement.createTextChild(")");
        } else if (call.value) {
            callViewElement.createTextChild(" = ");
            callViewElement.appendChild(WebInspector.CanvasProfileDataGridHelper.createCallArgumentElement(call.value));
        }

        if (call.result) {
            callViewElement.createTextChild(" => ");
            callViewElement.appendChild(WebInspector.CanvasProfileDataGridHelper.createCallArgumentElement(call.result));
        }

        var node = new WebInspector.DataGridNode(data);
        node.index = index;
        node.selectable = true;
        node.call = call;
        return node;
    },

    _popoverAnchor: function(element, event)
    {
        var argumentElement = element.enclosingNodeOrSelfWithClass("canvas-call-argument");
        if (!argumentElement || argumentElement.__suppressPopover)
            return null;
        return argumentElement;
    },

    _resolveObjectForPopover: function(argumentElement, showCallback, objectGroupName)
    {
        /**
         * @param {?Protocol.Error} error
         * @param {RuntimeAgent.RemoteObject=} result
         * @param {CanvasAgent.ResourceState=} resourceState
         */
        function showObjectPopover(error, result, resourceState)
        {
            if (error)
                return;

            // FIXME: handle resourceState also
            if (!result)
                return;

            this._popoverAnchorElement = argumentElement.cloneNode(true);
            this._popoverAnchorElement.addStyleClass("canvas-popover-anchor");
            this._popoverAnchorElement.addStyleClass("source-frame-eval-expression");
            argumentElement.parentElement.appendChild(this._popoverAnchorElement);

            var diffLeft = this._popoverAnchorElement.boxInWindow().x - argumentElement.boxInWindow().x;
            this._popoverAnchorElement.style.left = this._popoverAnchorElement.offsetLeft - diffLeft + "px";

            showCallback(WebInspector.RemoteObject.fromPayload(result), false, this._popoverAnchorElement);
        }

        var evalResult = argumentElement.__evalResult;
        if (evalResult)
            showObjectPopover.call(this, null, evalResult);
        else {
            var dataGridNode = this._logGrid.dataGridNodeFromNode(argumentElement);
            if (!dataGridNode || typeof dataGridNode.index !== "number") {
                this._popoverHelper.hidePopover();
                return;
            }
            var callIndex = dataGridNode.index;
            var argumentIndex = argumentElement.__argumentIndex;
            if (typeof argumentIndex !== "number")
                argumentIndex = -1;
            CanvasAgent.evaluateTraceLogCallArgument(this._traceLogId, callIndex, argumentIndex, objectGroupName, showObjectPopover.bind(this));
        }
    },

    /**
     * @param {WebInspector.RemoteObject} object
     * @return {string}
     */
    _hexNumbersFormatter: function(object)
    {
        if (object.type === "number") {
            // Show enum values in hex with min length of 4 (e.g. 0x0012).
            var str = "0000" + Number(object.description).toString(16).toUpperCase();
            str = str.replace(/^0+(.{4,})$/, "$1");
            return "0x" + str;
        }
        return object.description || "";
    },

    _onHidePopover: function()
    {
        if (this._popoverAnchorElement) {
            this._popoverAnchorElement.remove()
            delete this._popoverAnchorElement;
        }
    },

    _flattenSingleFrameNode: function()
    {
        var rootNode = this._logGrid.rootNode();
        if (rootNode.children.length !== 1)
            return;
        var frameNode = rootNode.children[0];
        while (frameNode.children[0])
            rootNode.appendChild(frameNode.children[0]);
        rootNode.removeChild(frameNode);
    },

    __proto__: WebInspector.View.prototype
}

/**
 * @constructor
 * @extends {WebInspector.ProfileType}
 */
WebInspector.CanvasProfileType = function()
{
    WebInspector.ProfileType.call(this, WebInspector.CanvasProfileType.TypeId, WebInspector.UIString("Capture Canvas Frame"));
    this._nextProfileUid = 1;
    this._recording = false;
    this._lastProfileHeader = null;

    this._capturingModeSelector = new WebInspector.StatusBarComboBox(this._dispatchViewUpdatedEvent.bind(this));
    this._capturingModeSelector.element.title = WebInspector.UIString("Canvas capture mode.");
    this._capturingModeSelector.createOption(WebInspector.UIString("Single Frame"), WebInspector.UIString("Capture a single canvas frame."), "");
    this._capturingModeSelector.createOption(WebInspector.UIString("Consecutive Frames"), WebInspector.UIString("Capture consecutive canvas frames."), "1");

    /** @type {!Object.<string, Element>} */
    this._frameOptions = {};

    /** @type {!Object.<string, boolean>} */
    this._framesWithCanvases = {};

    this._frameSelector = new WebInspector.StatusBarComboBox(this._dispatchViewUpdatedEvent.bind(this));
    this._frameSelector.element.title = WebInspector.UIString("Frame containing the canvases to capture.");
    this._frameSelector.element.addStyleClass("hidden");
    WebInspector.runtimeModel.contextLists().forEach(this._addFrame, this);
    WebInspector.runtimeModel.addEventListener(WebInspector.RuntimeModel.Events.FrameExecutionContextListAdded, this._frameAdded, this);
    WebInspector.runtimeModel.addEventListener(WebInspector.RuntimeModel.Events.FrameExecutionContextListRemoved, this._frameRemoved, this);

    this._dispatcher = new WebInspector.CanvasDispatcher(this);
    this._canvasAgentEnabled = false;

    this._decorationElement = document.createElement("div");
    this._decorationElement.className = "profile-canvas-decoration";
    this._updateDecorationElement();
}

WebInspector.CanvasProfileType.TypeId = "CANVAS_PROFILE";

WebInspector.CanvasProfileType.prototype = {
    get statusBarItems()
    {
        return [this._capturingModeSelector.element, this._frameSelector.element];
    },

    get buttonTooltip()
    {
        if (this._isSingleFrameMode())
            return WebInspector.UIString("Capture next canvas frame.");
        else
            return this._recording ? WebInspector.UIString("Stop capturing canvas frames.") : WebInspector.UIString("Start capturing canvas frames.");
    },

    /**
     * @override
     * @return {boolean}
     */
    buttonClicked: function()
    {
        if (!this._canvasAgentEnabled)
            return false;
        if (this._recording) {
            this._recording = false;
            this._stopFrameCapturing();
        } else if (this._isSingleFrameMode()) {
            this._recording = false;
            this._runSingleFrameCapturing();
        } else {
            this._recording = true;
            this._startFrameCapturing();
        }
        return this._recording;
    },

    _runSingleFrameCapturing: function()
    {
        var frameId = this._selectedFrameId();
        CanvasAgent.captureFrame(frameId, this._didStartCapturingFrame.bind(this, frameId));
    },

    _startFrameCapturing: function()
    {
        var frameId = this._selectedFrameId();
        CanvasAgent.startCapturing(frameId, this._didStartCapturingFrame.bind(this, frameId));
    },

    _stopFrameCapturing: function()
    {
        if (!this._lastProfileHeader)
            return;
        var profileHeader = this._lastProfileHeader;
        var traceLogId = profileHeader.traceLogId();
        this._lastProfileHeader = null;
        function didStopCapturing()
        {
            profileHeader._updateCapturingStatus();
        }
        CanvasAgent.stopCapturing(traceLogId, didStopCapturing.bind(this));
    },

    /**
     * @param {string|undefined} frameId
     * @param {?Protocol.Error} error
     * @param {CanvasAgent.TraceLogId} traceLogId
     */
    _didStartCapturingFrame: function(frameId, error, traceLogId)
    {
        if (error || this._lastProfileHeader && this._lastProfileHeader.traceLogId() === traceLogId)
            return;
        var profileHeader = new WebInspector.CanvasProfileHeader(this, WebInspector.UIString("Trace Log %d", this._nextProfileUid), this._nextProfileUid, traceLogId, frameId);
        ++this._nextProfileUid;
        this._lastProfileHeader = profileHeader;
        this.addProfile(profileHeader);
        profileHeader._updateCapturingStatus();
    },

    get treeItemTitle()
    {
        return WebInspector.UIString("CANVAS PROFILE");
    },

    get description()
    {
        return WebInspector.UIString("Canvas calls instrumentation");
    },

    /**
     * @override
     * @return {Element}
     */
    decorationElement: function()
    {
        return this._decorationElement;
    },

    /**
     * @override
     */
    _reset: function()
    {
        WebInspector.ProfileType.prototype._reset.call(this);
        this._nextProfileUid = 1;
    },

    /**
     * @override
     * @param {!WebInspector.ProfileHeader} profile
     */
    removeProfile: function(profile)
    {
        WebInspector.ProfileType.prototype.removeProfile.call(this, profile);
        if (this._recording && profile === this._lastProfileHeader)
            this._recording = false;
    },

    setRecordingProfile: function(isProfiling)
    {
        this._recording = isProfiling;
    },

    /**
     * @override
     * @param {string=} title
     * @return {!WebInspector.ProfileHeader}
     */
    createTemporaryProfile: function(title)
    {
        title = title || WebInspector.UIString("Capturing\u2026");
        return new WebInspector.CanvasProfileHeader(this, title);
    },

    /**
     * @override
     * @param {ProfilerAgent.ProfileHeader} profile
     * @return {!WebInspector.ProfileHeader}
     */
    createProfile: function(profile)
    {
        return new WebInspector.CanvasProfileHeader(this, profile.title, -1);
    },

    /**
     * @param {boolean=} forcePageReload
     */
    _updateDecorationElement: function(forcePageReload)
    {
        this._decorationElement.removeChildren();
        this._decorationElement.createChild("div", "warning-icon-small");
        this._decorationElement.appendChild(document.createTextNode(this._canvasAgentEnabled ? WebInspector.UIString("Canvas Profiler is enabled.") : WebInspector.UIString("Canvas Profiler is disabled.")));
        var button = this._decorationElement.createChild("button");
        button.type = "button";
        button.textContent = this._canvasAgentEnabled ? WebInspector.UIString("Disable") : WebInspector.UIString("Enable");
        button.addEventListener("click", this._onProfilerEnableButtonClick.bind(this, !this._canvasAgentEnabled), false);

        if (forcePageReload) {
            if (this._canvasAgentEnabled) {
                /**
                 * @param {?Protocol.Error} error
                 * @param {boolean} result
                 */
                function hasUninstrumentedCanvasesCallback(error, result)
                {
                    if (error || result)
                        PageAgent.reload();
                }
                CanvasAgent.hasUninstrumentedCanvases(hasUninstrumentedCanvasesCallback.bind(this));
            } else {
                for (var frameId in this._framesWithCanvases) {
                    if (this._framesWithCanvases.hasOwnProperty(frameId)) {
                        PageAgent.reload();
                        break;
                    }
                }
            }
        }
    },

    /**
     * @param {boolean} enable
     */
    _onProfilerEnableButtonClick: function(enable)
    {
        if (this._canvasAgentEnabled === enable)
            return;
        /**
         * @param {?Protocol.Error} error
         */
        function callback(error)
        {
            if (error)
                return;
            this._canvasAgentEnabled = enable;
            this._updateDecorationElement(true);
            this._dispatchViewUpdatedEvent();
        }
        if (enable)
            CanvasAgent.enable(callback.bind(this));
        else
            CanvasAgent.disable(callback.bind(this));
    },

    /**
     * @return {boolean}
     */
    _isSingleFrameMode: function()
    {
        return !this._capturingModeSelector.selectedOption().value;
    },

    /**
     * @param {WebInspector.Event} event
     */
    _frameAdded: function(event)
    {
        var contextList = /** @type {WebInspector.FrameExecutionContextList} */ (event.data);
        this._addFrame(contextList);
    },

    /**
     * @param {WebInspector.FrameExecutionContextList} contextList
     */
    _addFrame: function(contextList)
    {
        var frameId = contextList.frameId;
        var option = document.createElement("option");
        option.text = contextList.displayName;
        option.title = contextList.url;
        option.value = frameId;

        this._frameOptions[frameId] = option;

        if (this._framesWithCanvases[frameId]) {
            this._frameSelector.addOption(option);
            this._dispatchViewUpdatedEvent();
        }
    },

    /**
     * @param {WebInspector.Event} event
     */
    _frameRemoved: function(event)
    {
        var contextList = /** @type {WebInspector.FrameExecutionContextList} */ (event.data);
        var frameId = contextList.frameId;
        var option = this._frameOptions[frameId];
        if (option && this._framesWithCanvases[frameId]) {
            this._frameSelector.removeOption(option);
            this._dispatchViewUpdatedEvent();
        }
        delete this._frameOptions[frameId];
        delete this._framesWithCanvases[frameId];
    },

    /**
     * @param {string} frameId
     */
    _contextCreated: function(frameId)
    {
        if (this._framesWithCanvases[frameId])
            return;
        this._framesWithCanvases[frameId] = true;
        var option = this._frameOptions[frameId];
        if (option) {
            this._frameSelector.addOption(option);
            this._dispatchViewUpdatedEvent();
        }
    },

    /**
     * @param {PageAgent.FrameId=} frameId
     * @param {CanvasAgent.TraceLogId=} traceLogId
     */
    _traceLogsRemoved: function(frameId, traceLogId)
    {
        var sidebarElementsToDelete = [];
        var sidebarElements = /** @type {!Array.<WebInspector.ProfileSidebarTreeElement>} */ ((this.treeElement && this.treeElement.children) || []);
        for (var i = 0, n = sidebarElements.length; i < n; ++i) {
            var header = /** @type {WebInspector.CanvasProfileHeader} */ (sidebarElements[i].profile);
            if (!header)
                continue;
            if (frameId && frameId !== header.frameId())
                continue;
            if (traceLogId && traceLogId !== header.traceLogId())
                continue;
            sidebarElementsToDelete.push(sidebarElements[i]);
        }
        for (var i = 0, n = sidebarElementsToDelete.length; i < n; ++i)
            sidebarElementsToDelete[i].ondelete();
    },

    /**
     * @return {string|undefined}
     */
    _selectedFrameId: function()
    {
        var option = this._frameSelector.selectedOption();
        return option ? option.value : undefined;
    },

    _dispatchViewUpdatedEvent: function()
    {
        this._frameSelector.element.enableStyleClass("hidden", this._frameSelector.size() <= 1);
        this.dispatchEventToListeners(WebInspector.ProfileType.Events.ViewUpdated);
    },

    /**
     * @override
     * @return {boolean}
     */
    isInstantProfile: function()
    {
        return this._isSingleFrameMode();
    },

    /**
     * @override
     * @return {boolean}
     */
    isEnabled: function()
    {
        return this._canvasAgentEnabled;
    },

    __proto__: WebInspector.ProfileType.prototype
}

/**
 * @constructor
 * @implements {CanvasAgent.Dispatcher}
 * @param {WebInspector.CanvasProfileType} profileType
 */
WebInspector.CanvasDispatcher = function(profileType)
{
    this._profileType = profileType;
    InspectorBackend.registerCanvasDispatcher(this);
}

WebInspector.CanvasDispatcher.prototype = {
    /**
     * @param {string} frameId
     */
    contextCreated: function(frameId)
    {
        this._profileType._contextCreated(frameId);
    },

    /**
     * @param {PageAgent.FrameId=} frameId
     * @param {CanvasAgent.TraceLogId=} traceLogId
     */
    traceLogsRemoved: function(frameId, traceLogId)
    {
        this._profileType._traceLogsRemoved(frameId, traceLogId);
    }
}

/**
 * @constructor
 * @extends {WebInspector.ProfileHeader}
 * @param {!WebInspector.CanvasProfileType} type
 * @param {string} title
 * @param {number=} uid
 * @param {CanvasAgent.TraceLogId=} traceLogId
 * @param {PageAgent.FrameId=} frameId
 */
WebInspector.CanvasProfileHeader = function(type, title, uid, traceLogId, frameId)
{
    WebInspector.ProfileHeader.call(this, type, title, uid);
    /** @type {CanvasAgent.TraceLogId} */
    this._traceLogId = traceLogId || "";
    this._frameId = frameId;
    this._alive = true;
    this._traceLogSize = 0;
    this._traceLogPlayer = traceLogId ? new WebInspector.CanvasTraceLogPlayerProxy(traceLogId) : null;
}

WebInspector.CanvasProfileHeader.prototype = {
    /**
     * @return {CanvasAgent.TraceLogId}
     */
    traceLogId: function()
    {
        return this._traceLogId;
    },

    /**
     * @return {WebInspector.CanvasTraceLogPlayerProxy}
     */
    traceLogPlayer: function()
    {
        return this._traceLogPlayer;
    },

    /**
     * @return {PageAgent.FrameId|undefined}
     */
    frameId: function()
    {
        return this._frameId;
    },

    /**
     * @override
     * @return {WebInspector.ProfileSidebarTreeElement}
     */
    createSidebarTreeElement: function()
    {
        return new WebInspector.ProfileSidebarTreeElement(this, WebInspector.UIString("Trace Log %d"), "profile-sidebar-tree-item");
    },

    /**
     * @override
     * @param {WebInspector.ProfilesPanel} profilesPanel
     */
    createView: function(profilesPanel)
    {
        return new WebInspector.CanvasProfileView(this);
    },

    /**
     * @override
     */
    dispose: function()
    {
        if (this._traceLogPlayer)
            this._traceLogPlayer.dispose();
        clearTimeout(this._requestStatusTimer);
        this._alive = false;
    },

    /**
     * @param {CanvasAgent.TraceLog=} traceLog
     */
    _updateCapturingStatus: function(traceLog)
    {
        if (!this.sidebarElement || !this._traceLogId)
            return;

        if (traceLog) {
            this._alive = traceLog.alive;
            this._traceLogSize = traceLog.totalAvailableCalls;
        }

        this.sidebarElement.subtitle = this._alive ? WebInspector.UIString("Capturing\u2026 %d calls", this._traceLogSize) : WebInspector.UIString("Captured %d calls", this._traceLogSize);
        this.sidebarElement.wait = this._alive;

        if (this._alive) {
            clearTimeout(this._requestStatusTimer);
            this._requestStatusTimer = setTimeout(this._requestCapturingStatus.bind(this), WebInspector.CanvasProfileView.TraceLogPollingInterval);
        }
    },

    _requestCapturingStatus: function()
    {
        /**
         * @param {?CanvasAgent.TraceLog} traceLog
         */
        function didReceiveTraceLog(traceLog)
        {
            if (!traceLog)
                return;
            this._alive = traceLog.alive;
            this._traceLogSize = traceLog.totalAvailableCalls;
            this._updateCapturingStatus();
        }
        this._traceLogPlayer.getTraceLog(0, 0, didReceiveTraceLog.bind(this));
    },

    __proto__: WebInspector.ProfileHeader.prototype
}

WebInspector.CanvasProfileDataGridHelper = {
    /**
     * @param {!CanvasAgent.CallArgument} callArgument
     * @return {!Element}
     */
    createCallArgumentElement: function(callArgument)
    {
        if (callArgument.enumName)
            return WebInspector.CanvasProfileDataGridHelper.createEnumValueElement(callArgument.enumName, +callArgument.description);
        var element = document.createElement("span");
        element.className = "canvas-call-argument";
        var description = callArgument.description;
        if (callArgument.type === "string") {
            const maxStringLength = 150;
            element.createTextChild("\"");
            element.createChild("span", "canvas-formatted-string").textContent = description.trimMiddle(maxStringLength);
            element.createTextChild("\"");
            element.__suppressPopover = (description.length <= maxStringLength && !/[\r\n]/.test(description));
            if (!element.__suppressPopover)
                element.__evalResult = WebInspector.RemoteObject.fromPrimitiveValue(description);
        } else {
            var type = callArgument.subtype || callArgument.type;
            if (type) {
                element.addStyleClass("canvas-formatted-" + type);
                if (["null", "undefined", "boolean", "number"].indexOf(type) >= 0)
                    element.__suppressPopover = true;
            }
            element.textContent = description;
            if (callArgument.remoteObject)
                element.__evalResult = WebInspector.RemoteObject.fromPayload(callArgument.remoteObject);
        }
        if (callArgument.resourceId) {
            element.addStyleClass("canvas-formatted-resource");
            element.__resourceId = callArgument.resourceId;
        }
        return element;
    },

    /**
     * @param {string} enumName
     * @param {number} enumValue
     * @return {!Element}
     */
    createEnumValueElement: function(enumName, enumValue)
    {
        var element = document.createElement("span");
        element.className = "canvas-call-argument canvas-formatted-number";
        element.textContent = enumName;
        element.__evalResult = WebInspector.RemoteObject.fromPrimitiveValue(enumValue);
        return element;
    }
}

/**
 * @extends {WebInspector.Object}
 * @constructor
 * @param {CanvasAgent.TraceLogId} traceLogId
 */
WebInspector.CanvasTraceLogPlayerProxy = function(traceLogId)
{
    this._traceLogId = traceLogId;
    /** @type {!Object.<string, !CanvasAgent.ResourceState>} */
    this._currentResourceStates = {};
    /** @type {?CanvasAgent.ResourceId} */
    this._defaultResourceId = null;
}

/** @enum {string} */
WebInspector.CanvasTraceLogPlayerProxy.Events = {
    CanvasTraceLogReceived: "CanvasTraceLogReceived",
    CanvasReplayStateChanged: "CanvasReplayStateChanged",
    CanvasResourceStateReceived: "CanvasResourceStateReceived",
}

WebInspector.CanvasTraceLogPlayerProxy.prototype = {
    /**
     * @param {number|undefined} startOffset
     * @param {number|undefined} maxLength
     * @param {function(?CanvasAgent.TraceLog):void} userCallback
     */
    getTraceLog: function(startOffset, maxLength, userCallback)
    {
        /**
         * @param {?Protocol.Error} error
         * @param {CanvasAgent.TraceLog} traceLog
         */
        function callback(error, traceLog)
        {
            if (error || !traceLog) {
                userCallback(null);
                return;
            }
            userCallback(traceLog);
            this.dispatchEventToListeners(WebInspector.CanvasTraceLogPlayerProxy.Events.CanvasTraceLogReceived, traceLog);
        }
        CanvasAgent.getTraceLog(this._traceLogId, startOffset, maxLength, callback.bind(this));
    },

    dispose: function()
    {
        this._currentResourceStates = {};
        CanvasAgent.dropTraceLog(this._traceLogId);
        this.dispatchEventToListeners(WebInspector.CanvasTraceLogPlayerProxy.Events.CanvasReplayStateChanged);
    },

    /**
     * @param {?CanvasAgent.ResourceId} resourceId
     * @param {function(?CanvasAgent.ResourceState):void} userCallback
     */
    getResourceState: function(resourceId, userCallback)
    {
        resourceId = resourceId || this._defaultResourceId;
        if (!resourceId) {
            userCallback(null); // Has not been replayed yet.
            return;
        }
        if (this._currentResourceStates[resourceId]) {
            userCallback(this._currentResourceStates[resourceId]);
            return;
        }
        /**
         * @param {?Protocol.Error} error
         * @param {CanvasAgent.ResourceState} resourceState
         */
        function callback(error, resourceState)
        {
            if (error || !resourceState) {
                userCallback(null);
                return;
            }
            this._currentResourceStates[resourceId] = resourceState;
            userCallback(resourceState);
            this.dispatchEventToListeners(WebInspector.CanvasTraceLogPlayerProxy.Events.CanvasResourceStateReceived, resourceState);
        }
        CanvasAgent.getResourceState(this._traceLogId, resourceId, callback.bind(this));
    },

    /**
     * @param {number} index
     * @param {function(?CanvasAgent.ResourceState, number):void} userCallback
     */
    replayTraceLog: function(index, userCallback)
    {
        /**
         * @param {?Protocol.Error} error
         * @param {CanvasAgent.ResourceState} resourceState
         * @param {number} replayTime
         */
        function callback(error, resourceState, replayTime)
        {
            this._currentResourceStates = {};
            if (error || !resourceState) {
                resourceState = null;
                userCallback(null, replayTime);
            } else {
                this._defaultResourceId = resourceState.id;
                this._currentResourceStates[resourceState.id] = resourceState;
                userCallback(resourceState, replayTime);
            }
            this.dispatchEventToListeners(WebInspector.CanvasTraceLogPlayerProxy.Events.CanvasReplayStateChanged);
            if (resourceState)
                this.dispatchEventToListeners(WebInspector.CanvasTraceLogPlayerProxy.Events.CanvasResourceStateReceived, resourceState);
        }
        CanvasAgent.replayTraceLog(this._traceLogId, index, callback.bind(this));
    },

    clearResourceStates: function()
    {
        this._currentResourceStates = {};
        this.dispatchEventToListeners(WebInspector.CanvasTraceLogPlayerProxy.Events.CanvasReplayStateChanged);
    },

    __proto__: WebInspector.Object.prototype
}
