/*
 * Copyright (C) 2011 Google Inc.  All rights reserved.
 * Copyright (C) 2007, 2008, 2013-2015 Apple Inc.  All rights reserved.
 * Copyright (C) 2009 Joseph Pecoraro
 *
 * 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.
 * 3.  Neither the name of Apple Inc. ("Apple") 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 APPLE 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 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.ConsoleMessageView = class ConsoleMessageView extends WI.Object
{
    constructor(message)
    {
        super();

        console.assert(message instanceof WI.ConsoleMessage);

        this._message = message;
        this._expandable = false;
        this._repeatCount = message._repeatCount || 0;

        // These are the parameters unused by the messages's optional format string.
        // Any extra parameters will be displayed as children of this message.
        this._extraParameters = message.parameters;
    }

    // Public

    render()
    {
        this._element = document.createElement("div");
        this._element.classList.add("console-message");
        this._element.dir = "ltr";

        // FIXME: <https://webkit.org/b/143545> Web Inspector: LogContentView should use higher level objects
        this._element.__message = this._message;
        this._element.__messageView = this;

        if (this._message.type === WI.ConsoleMessage.MessageType.Result) {
            this._element.classList.add("console-user-command-result");
            this._element.setAttribute("data-labelprefix", WI.UIString("Output: "));
        } else if (this._message.type === WI.ConsoleMessage.MessageType.StartGroup || this._message.type === WI.ConsoleMessage.MessageType.StartGroupCollapsed)
            this._element.classList.add("console-group-title");

        switch (this._message.level) {
        case WI.ConsoleMessage.MessageLevel.Log:
            this._element.classList.add("console-log-level");
            this._element.setAttribute("data-labelprefix", WI.UIString("Log: "));
            break;
        case WI.ConsoleMessage.MessageLevel.Info:
            this._element.classList.add("console-info-level");
            this._element.setAttribute("data-labelprefix", WI.UIString("Info: "));
            break;
        case WI.ConsoleMessage.MessageLevel.Debug:
            this._element.classList.add("console-debug-level");
            this._element.setAttribute("data-labelprefix", WI.UIString("Debug: "));
            break;
        case WI.ConsoleMessage.MessageLevel.Warning:
            this._element.classList.add("console-warning-level");
            this._element.setAttribute("data-labelprefix", WI.UIString("Warning: "));
            break;
        case WI.ConsoleMessage.MessageLevel.Error:
            this._element.classList.add("console-error-level");
            this._element.setAttribute("data-labelprefix", WI.UIString("Error: "));
            break;
        }

        // FIXME: The location link should include stack trace information.
        this._appendLocationLink();

        this._messageBodyElement = this._element.appendChild(document.createElement("span"));
        this._messageBodyElement.classList.add("console-top-level-message", "console-message-body");
        this._appendMessageTextAndArguments(this._messageBodyElement);
        this._appendSavedResultIndex();

        this._appendExtraParameters();
        this._appendStackTrace();

        this._renderRepeatCount();

        if (this._message.type === WI.ConsoleMessage.MessageType.Dir)
            this.expand();
        else if (this._message.type === WI.ConsoleMessage.MessageType.Image) {
            this._element.classList.add("console-image");
            this._element.addEventListener("contextmenu", this._handleContextMenu.bind(this));
        }
    }

    get element()
    {
        return this._element;
    }

    get message()
    {
        return this._message;
    }

    get repeatCount()
    {
        return this._repeatCount;
    }

    set repeatCount(count)
    {
        console.assert(typeof count === "number");

        if (this._repeatCount === count)
            return;

        this._repeatCount = count;

        if (this._element)
            this._renderRepeatCount();
    }

    _renderRepeatCount()
    {
        let count = this._repeatCount;

        if (count <= 1) {
            if (this._repeatCountElement) {
                this._repeatCountElement.remove();
                this._repeatCountElement = null;
            }
            return;
        }

        if (!this._repeatCountElement) {
            this._repeatCountElement = document.createElement("span");
            this._repeatCountElement.classList.add("repeat-count");
            this._element.insertBefore(this._repeatCountElement, this._element.firstChild);
        }

        this._repeatCountElement.textContent = Number.abbreviate(count);
    }

    get expandable()
    {
        // There are extra arguments or a call stack that can be shown.
        if (this._expandable)
            return true;

        // There is an object tree that could be expanded.
        if (this._objectTree)
            return true;

        return false;
    }

    expand()
    {
        if (this._expandable)
            this._element.classList.add("expanded");

        // Auto-expand an inner object tree if there is a single object.
        // For Trace messages we are auto-expanding for the call stack, don't also auto-expand an object as well.
        if (this._objectTree && this._message.type !== WI.ConsoleMessage.MessageType.Trace) {
            if (!this._extraParameters || this._extraParameters.length <= 1)
                this._objectTree.expand();
        }
    }

    collapse()
    {
        if (this._expandable)
            this._element.classList.remove("expanded");

        // Collapse the object tree just in cases where it was autoexpanded.
        if (this._objectTree) {
            if (!this._extraParameters || this._extraParameters.length <= 1)
                this._objectTree.collapse();
        }
    }

    toggle()
    {
        if (this._element.classList.contains("expanded"))
            this.collapse();
        else
            this.expand();
    }

    toClipboardString(isPrefixOptional)
    {
        let clipboardString = this._messageBodyElement.innerText.removeWordBreakCharacters();
        if (this._message.savedResultIndex)
            clipboardString = clipboardString.replace(new RegExp(`\\s*=\\s*(${WI.RuntimeManager.preferredSavedResultPrefix()}\\d+)$`), "");

        let hasStackTrace = this._shouldShowStackTrace();
        if (!hasStackTrace) {
            let repeatString = this.repeatCount > 1 ? "x" + this.repeatCount : "";
            let urlLine = "";
            if (this._message.url) {
                let components = [WI.displayNameForURL(this._message.url), "line " + this._message.line];
                if (repeatString)
                    components.push(repeatString);
                urlLine = " (" + components.join(", ") + ")";
            } else if (repeatString)
                urlLine = " (" + repeatString + ")";

            if (urlLine) {
                let lines = clipboardString.split("\n");
                lines[0] += urlLine;
                clipboardString = lines.join("\n");
            }
        }

        if (this._extraElementsList)
            clipboardString += "\n" + this._extraElementsList.innerText.removeWordBreakCharacters().trim();

        if (hasStackTrace) {
            this._message.stackTrace.callFrames.forEach(function(frame) {
                clipboardString += "\n\t" + (frame.functionName || WI.UIString("(anonymous function)"));
                if (frame.sourceCodeLocation)
                    clipboardString += " (" + frame.sourceCodeLocation.originalLocationString() + ")";
            });
        }

        if (!isPrefixOptional || this._enforcesClipboardPrefixString())
            return this._clipboardPrefixString() + clipboardString;
        return clipboardString;
    }

    removeEventListeners()
    {
        // FIXME: <https://webkit.org/b/196956> Web Inspector: use weak collections for holding event listeners
        WI.settings.consoleSavedResultAlias.removeEventListener(null, null, this);
    }

    // Private

    _appendMessageTextAndArguments(element)
    {
        if (this._message.source === WI.ConsoleMessage.MessageSource.ConsoleAPI) {
            switch (this._message.type) {
            case WI.ConsoleMessage.MessageType.Trace:
                var args = [WI.UIString("Trace")];
                if (this._message.parameters) {
                    if (this._message.parameters[0].type === "string") {
                        var prefixedFormatString = WI.UIString("Trace: %s").format(this._message.parameters[0].description);
                        args = [prefixedFormatString].concat(this._message.parameters.slice(1));
                    } else
                        args.pushAll(this._message.parameters);
                }
                this._appendFormattedArguments(element, args);
                return;

            case WI.ConsoleMessage.MessageType.Assert:
                var args = [WI.UIString("Assertion Failed")];
                if (this._message.parameters) {
                    if (this._message.parameters[0].type === "string") {
                        var prefixedFormatString = WI.UIString("Assertion Failed: %s").format(this._message.parameters[0].description);
                        args = [prefixedFormatString].concat(this._message.parameters.slice(1));
                    } else
                        args.pushAll(this._message.parameters);
                }
                this._appendFormattedArguments(element, args);
                return;

            case WI.ConsoleMessage.MessageType.Dir:
                var obj = this._message.parameters ? this._message.parameters[0] : undefined;
                this._appendFormattedArguments(element, ["%O", obj]);
                return;

            case WI.ConsoleMessage.MessageType.Table:
                var args = this._message.parameters;
                element.appendChild(this._formatParameterAsTable(args));
                this._extraParameters = null;
                return;

            case WI.ConsoleMessage.MessageType.StartGroup:
            case WI.ConsoleMessage.MessageType.StartGroupCollapsed:
                var args = this._message.parameters || [this._message.messageText || WI.UIString("Group")];
                this._formatWithSubstitutionString(args, element);
                this._extraParameters = null;
                return;

            case WI.ConsoleMessage.MessageType.Timing: {
                let args = [this._message.messageText];
                if (this._extraParameters)
                    args.pushAll(this._extraParameters);
                this._appendFormattedArguments(element, args);
                return;
            }

            case WI.ConsoleMessage.MessageType.Image: {
                if (this._message.level === WI.ConsoleMessage.MessageLevel.Log) {
                    let divider = null;

                    if (this._message.parameters.length > 1) {
                        this._appendFormattedArguments(element, this._message.parameters.slice(1));

                        divider = element.appendChild(document.createElement("hr"));
                    }

                    let target = this._message.parameters[0];
                    if (target === "Viewport")
                        target = WI.UIString("Viewport");
                    this._appendFormattedArguments(element, [target]);

                    if (this._message.messageText) {
                        let img = document.createElement("img");
                        img.classList.add("show-grid");
                        img.src = this._message.messageText;
                        img.setAttribute("filename", WI.FileUtilities.screenshotString() + ".png");
                        img.addEventListener("load", (event) => {
                            if (img.width >= img.height)
                                img.width = img.width / window.devicePixelRatio;
                            else
                                img.height = img.height / window.devicePixelRatio;
                            element.appendChild(img);
                        });
                        img.addEventListener("error", (event) => {
                            this._element.setAttribute("data-labelprefix", WI.UIString("Error: "));
                            this._element.classList.add("console-error-level");
                            this._element.classList.remove("console-log-level");

                            if (divider) {
                                while (divider.nextSibling)
                                    divider.nextSibling.remove();
                            } else
                                element.removeChildren();

                            let args = [WI.UIString("Could not capture screenshot"), this._message.messageText];
                            if (this._extraParameters)
                                args.pushAll(this._extraParameters);
                            this._appendFormattedArguments(element, args);
                        });
                    }
                    return;
                }

                if (this._message.level === WI.ConsoleMessage.MessageLevel.Error) {
                    let args = [];
                    if (this._message.messageText === "Could not capture screenshot")
                        args.push(WI.UIString("Could not capture screenshot"));
                    else
                        args.push(this._message.messageText);
                    if (this._extraParameters)
                        args.pushAll(this._extraParameters);
                    this._appendFormattedArguments(element, args);
                    return;
                }

                console.assert();
                break;
            }
            }
        }

        // FIXME: Better handle WI.ConsoleMessage.MessageSource.Network once it has request info.

        var args = this._message.parameters || [this._message.messageText];
        this._appendFormattedArguments(element, args);
    }

    _appendSavedResultIndex(element)
    {
        let savedResultIndex = this._message.savedResultIndex;
        if (!savedResultIndex)
            return;

        console.assert(this._message instanceof WI.ConsoleCommandResultMessage);
        console.assert(this._message.type === WI.ConsoleMessage.MessageType.Result);

        var savedVariableElement = document.createElement("span");
        savedVariableElement.classList.add("console-saved-variable");

        // FIXME: <https://webkit.org/b/196956> Web Inspector: use weak collections for holding event listeners
        function updateSavedVariableText() {
            savedVariableElement.textContent = " = " + WI.RuntimeManager.preferredSavedResultPrefix() + savedResultIndex;
        }
        WI.settings.consoleSavedResultAlias.addEventListener(WI.Setting.Event.Changed, updateSavedVariableText, this);
        updateSavedVariableText();

        if (this._objectTree)
            this._objectTree.appendTitleSuffix(savedVariableElement);
        else
            this._messageBodyElement.appendChild(savedVariableElement);
    }

    _appendLocationLink()
    {
        if (this._message.source === WI.ConsoleMessage.MessageSource.Network) {
            if (this._message.url) {
                var anchor = WI.linkifyURLAsNode(this._message.url, this._message.url, "console-message-url");
                anchor.classList.add("console-message-location");
                this._element.appendChild(anchor);
            }
            return;
        }

        var firstNonNativeNonAnonymousCallFrame = this._message.stackTrace.firstNonNativeNonAnonymousCallFrame;

        var callFrame;
        if (firstNonNativeNonAnonymousCallFrame) {
            // JavaScript errors and console.* methods.
            callFrame = firstNonNativeNonAnonymousCallFrame;
        } else if (this._message.url && !this._shouldHideURL(this._message.url)) {
            // CSS warnings have no stack traces.
            callFrame = WI.CallFrame.fromPayload(this._message.target, {
                functionName: "",
                url: this._message.url,
                lineNumber: this._message.line,
                columnNumber: this._message.column
            });
        }

        if (callFrame && (!callFrame.isConsoleEvaluation || (WI.isDebugUIEnabled() && WI.settings.debugShowConsoleEvaluations.value))) {
            const showFunctionName = !!callFrame.functionName;
            var locationElement = new WI.CallFrameView(callFrame, showFunctionName);
            locationElement.classList.add("console-message-location");
            this._element.appendChild(locationElement);
            return;
        }

        if (this._message.parameters && this._message.parameters.length === 1) {
            var parameter = this._createRemoteObjectIfNeeded(this._message.parameters[0]);

            parameter.findFunctionSourceCodeLocation().then((result) => {
                if (result === WI.RemoteObject.SourceCodeLocationPromise.NoSourceFound || result === WI.RemoteObject.SourceCodeLocationPromise.MissingObjectId)
                    return;

                let link = WI.linkifySourceCode(result.sourceCode, new WI.SourceCodePosition(result.lineNumber, result.columnNumber), {
                    className: "console-message-url",
                    ignoreNetworkTab: true,
                    ignoreSearchTab: true,
                });
                link.classList.add("console-message-location");

                if (this._element.hasChildNodes())
                    this._element.insertBefore(link, this._element.firstChild);
                else
                    this._element.appendChild(link);
            });
        }
    }

    _appendExtraParameters()
    {
        if (!this._extraParameters || !this._extraParameters.length)
            return;

        this._makeExpandable();

        // Auto-expand if there are multiple objects or if there were simple parameters.
        if (this._extraParameters.length > 1)
            this.expand();

        this._extraElementsList = this._element.appendChild(document.createElement("ol"));
        this._extraElementsList.classList.add("console-message-extra-parameters-container");

        for (var parameter of this._extraParameters) {
            var listItemElement = this._extraElementsList.appendChild(document.createElement("li"));
            const forceObjectFormat = parameter.type === "object" && (parameter.subtype !== "null" && parameter.subtype !== "regexp" && parameter.subtype !== "node" && parameter.subtype !== "error");
            listItemElement.classList.add("console-message-extra-parameter");
            listItemElement.appendChild(this._formatParameter(parameter, forceObjectFormat));
        }
    }

    _appendStackTrace()
    {
        if (!this._shouldShowStackTrace())
            return;

        this._makeExpandable();

        if (this._message.type === WI.ConsoleMessage.MessageType.Trace && WI.settings.consoleAutoExpandTrace.value)
            this.expand();

        this._stackTraceElement = this._element.appendChild(document.createElement("div"));
        this._stackTraceElement.classList.add("console-message-body", "console-message-stack-trace-container");

        var callFramesElement = new WI.StackTraceView(this._message.stackTrace).element;
        this._stackTraceElement.appendChild(callFramesElement);
    }

    _createRemoteObjectIfNeeded(parameter)
    {
        // FIXME: Only pass RemoteObjects here so we can avoid this work.
        if (parameter instanceof WI.RemoteObject)
            return parameter;

        if (typeof parameter === "object")
            return WI.RemoteObject.fromPayload(parameter, this._message.target);

        return WI.RemoteObject.fromPrimitiveValue(parameter);
    }

    _appendFormattedArguments(element, parameters)
    {
        if (!parameters.length)
            return;

        for (let i = 0; i < parameters.length; ++i)
            parameters[i] = this._createRemoteObjectIfNeeded(parameters[i]);

        let builderElement = element.appendChild(document.createElement("span"));
        let shouldFormatWithStringSubstitution = parameters[0].type === "string" && this._message.type !== WI.ConsoleMessage.MessageType.Result;

        // Single object (e.g. console result or logging a non-string object).
        if (parameters.length === 1 && !shouldFormatWithStringSubstitution) {
            this._extraParameters = null;
            builderElement.appendChild(this._formatParameter(parameters[0], false));
            return;
        }

        console.assert(this._message.type !== WI.ConsoleMessage.MessageType.Result);

        if (shouldFormatWithStringSubstitution && this._isStackTrace(parameters[0]))
            shouldFormatWithStringSubstitution = false;

        let needsDivider = false;
        function appendDividerIfNeeded() {
            if (!needsDivider)
                return null;
            let element = builderElement.appendChild(document.createElement("span"));
            element.classList.add("console-message-preview-divider");
            element.textContent = ` ${enDash} `;
            return element;
        }

        // Format string.
        if (shouldFormatWithStringSubstitution) {
            let result = this._formatWithSubstitutionString(parameters, builderElement);
            parameters = result.unusedSubstitutions;
            this._extraParameters = parameters;
            needsDivider = true;
        }

        // Trailing inline parameters.
        if (parameters.length) {
            let simpleParametersCount = 0;
            for (let parameter of parameters) {
                if (!this._hasSimpleDisplay(parameter))
                    break;
                simpleParametersCount++;
            }

            // Show one or more simple parameters inline on the message line.
            if (simpleParametersCount) {
                let simpleParameters = parameters.splice(0, simpleParametersCount);
                this._extraParameters = parameters;

                for (let parameter of simpleParameters) {
                    let dividerElement = appendDividerIfNeeded();
                    if (dividerElement)
                        dividerElement.classList.add("inline-lossless");

                    let previewContainer = builderElement.appendChild(document.createElement("span"));
                    previewContainer.classList.add("inline-lossless");

                    let preview = WI.FormattedValue.createObjectPreviewOrFormattedValueForRemoteObject(parameter, WI.ObjectPreviewView.Mode.Brief);
                    let isPreviewView = preview instanceof WI.ObjectPreviewView;

                    if (isPreviewView)
                        preview.setOriginatingObjectInfo(parameter, null);

                    let previewElement = isPreviewView ? preview.element : preview;
                    previewContainer.appendChild(previewElement);

                    needsDivider = true;

                    // Simple displayable parameters should pretty much always be lossless.
                    // An exception might be a truncated string.
                    console.assert((isPreviewView && preview.lossless) || (!isPreviewView && this._shouldConsiderObjectLossless(parameter)));
                }
            }

            // If there is a single non-simple parameter after simple paramters, show it inline.
            if (parameters.length === 1 && !this._isStackTrace(parameters[0])) {
                let parameter = parameters[0];

                let dividerElement = appendDividerIfNeeded();

                let previewContainer = builderElement.appendChild(document.createElement("span"));
                previewContainer.classList.add("console-message-preview");

                let preview = WI.FormattedValue.createObjectPreviewOrFormattedValueForRemoteObject(parameter, WI.ObjectPreviewView.Mode.Brief);
                let isPreviewView = preview instanceof WI.ObjectPreviewView;

                if (isPreviewView)
                    preview.setOriginatingObjectInfo(parameter, null);

                let previewElement = isPreviewView ? preview.element : preview;
                previewContainer.appendChild(previewElement);

                needsDivider = true;

                // If this preview is effectively lossless, we can avoid making this console message expandable.
                if ((isPreviewView && preview.lossless) || (!isPreviewView && this._shouldConsiderObjectLossless(parameter))) {
                    this._extraParameters = null;
                    if (dividerElement)
                        dividerElement.classList.add("inline-lossless");
                    previewContainer.classList.add("inline-lossless");
                }
            } else if (parameters.length) {
                // Multiple remaining objects. Show an indicator and they will be appended as extra parameters.
                let enclosedElement = document.createElement("span");
                builderElement.append(" ", enclosedElement);
                enclosedElement.classList.add("console-message-enclosed");
                enclosedElement.textContent = "(" + parameters.length + ")";
            }
        }
    }

    _hasSimpleDisplay(parameter)
    {
        console.assert(parameter instanceof WI.RemoteObject);

        return WI.FormattedValue.hasSimpleDisplay(parameter) && !this._isStackTrace(parameter);
    }

    _isStackTrace(parameter)
    {
        console.assert(parameter instanceof WI.RemoteObject);

        return parameter.type === "string" && WI.StackTrace.isLikelyStackTrace(parameter.description);
    }

    _shouldConsiderObjectLossless(object)
    {
        if (object.type === "string") {
            const description = object.description;
            const maxLength = WI.FormattedValue.MAX_PREVIEW_STRING_LENGTH;
            const longOrMultiLineString = description.length > maxLength || description.slice(0, maxLength).includes("\n");
            return !longOrMultiLineString;
        }

        return object.type !== "object" || object.subtype === "null" || object.subtype === "regexp";
    }

    _formatParameter(parameter, forceObjectFormat)
    {
        var type;
        if (forceObjectFormat)
            type = "object";
        else if (parameter instanceof WI.RemoteObject)
            type = parameter.subtype || parameter.type;
        else {
            console.assert(false, "no longer reachable");
            type = typeof parameter;
        }

        var formatters = {
            "object": this._formatParameterAsObject,
            "error": this._formatParameterAsError,
            "map": this._formatParameterAsObject,
            "set": this._formatParameterAsObject,
            "weakmap": this._formatParameterAsObject,
            "weakset": this._formatParameterAsObject,
            "iterator": this._formatParameterAsObject,
            "class": this._formatParameterAsObject,
            "proxy": this._formatParameterAsObject,
            "array": this._formatParameterAsArray,
            "node": this._formatParameterAsNode,
            "string": this._formatParameterAsString,
        };

        var formatter = formatters[type] || this._formatParameterAsValue;

        const fragment = document.createDocumentFragment();
        formatter.call(this, parameter, fragment, forceObjectFormat);
        return fragment;
    }

    _formatParameterAsValue(value, fragment)
    {
        fragment.appendChild(WI.FormattedValue.createElementForRemoteObject(value));
    }

    _formatParameterAsString(object, fragment)
    {
        if (this._isStackTrace(object)) {
            let stackTrace = WI.StackTrace.fromString(this._message.target, object.description);
            if (stackTrace.callFrames.length) {
                let stackView = new WI.StackTraceView(stackTrace);
                fragment.appendChild(stackView.element);
                return;
            }
        }

        fragment.appendChild(WI.FormattedValue.createLinkifiedElementString(object.description));
    }

    _formatParameterAsNode(object, fragment)
    {
        fragment.appendChild(WI.FormattedValue.createElementForNode(object));
    }

    _formatParameterAsObject(object, fragment, forceExpansion)
    {
        // FIXME: Should have a better ObjectTreeView mode for classes (static methods and methods).
        this._objectTree = new WI.ObjectTreeView(object, null, this._rootPropertyPathForObject(object), forceExpansion);
        fragment.appendChild(this._objectTree.element);
    }

    _formatParameterAsError(object, fragment)
    {
        this._objectTree = new WI.ErrorObjectView(object);
        fragment.appendChild(this._objectTree.element);
    }

    _formatParameterAsArray(array, fragment)
    {
        this._objectTree = new WI.ObjectTreeView(array, WI.ObjectTreeView.Mode.Properties, this._rootPropertyPathForObject(array));
        fragment.appendChild(this._objectTree.element);
    }

    _rootPropertyPathForObject(object)
    {
        let savedResultIndex = this._message.savedResultIndex;
        if (!savedResultIndex)
            return null;

        function prefixSavedResultIndex() {
            return WI.RuntimeManager.preferredSavedResultPrefix() + savedResultIndex;
        }

        let propertyPath = new WI.PropertyPath(object, prefixSavedResultIndex());

        // FIXME: <https://webkit.org/b/196956> Web Inspector: use weak collections for holding event listeners
        WI.settings.consoleSavedResultAlias.addEventListener(WI.Setting.Event.Changed, (event) => {
            propertyPath.pathComponent = prefixSavedResultIndex();
        }, this);

        return propertyPath;
    }

    _formatWithSubstitutionString(parameters, formattedResult)
    {
        function parameterFormatter(force, obj)
        {
            return this._formatParameter(obj, force);
        }

        function stringFormatter(obj)
        {
            return obj.description;
        }

        function floatFormatter(obj, token)
        {
            let value = typeof obj.value === "number" ? obj.value : obj.description;
            return String.standardFormatters.f(value, token);
        }

        function integerFormatter(obj)
        {
            let value = typeof obj.value === "number" ? obj.value : obj.description;
            return String.standardFormatters.d(value);
        }

        var currentStyle = null;
        function styleFormatter(obj)
        {
            currentStyle = {};
            var buffer = document.createElement("span");
            buffer.setAttribute("style", obj.description);
            for (var i = 0; i < buffer.style.length; i++) {
                var property = buffer.style[i];
                if (isWhitelistedProperty(property))
                    currentStyle[property] = buffer.style[property];
            }
        }

        function isWhitelistedProperty(property)
        {
            for (var prefix of ["background", "border", "color", "font", "line", "margin", "padding", "text"]) {
                if (property.startsWith(prefix) || property.startsWith("-webkit-" + prefix))
                    return true;
            }
            return false;
        }

        // Firebug uses %o for formatting objects.
        var formatters = {};
        formatters.o = parameterFormatter.bind(this, false);
        formatters.s = stringFormatter;
        formatters.f = floatFormatter;

        // Firebug allows both %i and %d for formatting integers.
        formatters.i = integerFormatter;
        formatters.d = integerFormatter;

        // Firebug uses %c for styling the message.
        formatters.c = styleFormatter;

        // Support %O to force object formatting, instead of the type-based %o formatting.
        formatters.O = parameterFormatter.bind(this, true);

        function append(a, b)
        {
            if (b instanceof Node)
                a.appendChild(b);
            else if (b !== undefined) {
                var toAppend = WI.linkifyStringAsFragment(b.toString());
                if (currentStyle) {
                    var wrapper = document.createElement("span");
                    for (var key in currentStyle)
                        wrapper.style[key] = currentStyle[key];
                    wrapper.appendChild(toAppend);
                    toAppend = wrapper;
                }

                a.appendChild(toAppend);
            }
            return a;
        }

        // String.format does treat formattedResult like a Builder, result is an object.
        return String.format(parameters[0].description, parameters.slice(1), formatters, formattedResult, append);
    }

    _shouldShowStackTrace()
    {
        if (!this._message.stackTrace.callFrames.length)
            return false;

        return this._message.source === WI.ConsoleMessage.MessageSource.Network
            || this._message.level === WI.ConsoleMessage.MessageLevel.Error
            || this._message.type === WI.ConsoleMessage.MessageType.Trace;
    }

    _shouldHideURL(url)
    {
        return url === "undefined" || url === "[native code]";
    }

    _userProvidedColumnNames(columnNamesArgument)
    {
        if (!columnNamesArgument)
            return null;

        console.assert(columnNamesArgument instanceof WI.RemoteObject);

        // Single primitive argument.
        if (columnNamesArgument.type === "string" || columnNamesArgument.type === "number")
            return [String(columnNamesArgument.value)];

        // Ignore everything that is not an array with property previews.
        if (columnNamesArgument.type !== "object" || columnNamesArgument.subtype !== "array" || !columnNamesArgument.preview || !columnNamesArgument.preview.propertyPreviews)
            return null;

        // Array. Look into the preview and get string values.
        var extractedColumnNames = [];
        for (var propertyPreview of columnNamesArgument.preview.propertyPreviews) {
            if (propertyPreview.type === "string" || propertyPreview.type === "number")
                extractedColumnNames.push(String(propertyPreview.value));
        }

        return extractedColumnNames.length ? extractedColumnNames : null;
    }

    _formatParameterAsTable(parameters)
    {
        var element = document.createElement("span");
        var table = parameters[0];
        if (!table || !table.preview)
            return element;

        var rows = [];
        var columnNames = [];
        var flatValues = [];
        var preview = table.preview;
        var userProvidedColumnNames = false;

        // User provided columnNames.
        var extractedColumnNames = this._userProvidedColumnNames(parameters[1]);
        if (extractedColumnNames) {
            userProvidedColumnNames = true;
            columnNames = extractedColumnNames;
        }

        // Check first for valuePreviews in the properties meaning this was an array of objects.
        if (preview.propertyPreviews) {
            for (var i = 0; i < preview.propertyPreviews.length; ++i) {
                var rowProperty = preview.propertyPreviews[i];
                var rowPreview = rowProperty.valuePreview;
                if (!rowPreview || !rowPreview.propertyPreviews)
                    continue;

                var rowValue = {};
                var maxColumnsToRender = 15;
                for (var j = 0; j < rowPreview.propertyPreviews.length; ++j) {
                    var cellProperty = rowPreview.propertyPreviews[j];
                    var columnRendered = columnNames.includes(cellProperty.name);
                    if (!columnRendered) {
                        if (userProvidedColumnNames || columnNames.length === maxColumnsToRender)
                            continue;
                        columnRendered = true;
                        columnNames.push(cellProperty.name);
                    }

                    rowValue[cellProperty.name] = WI.FormattedValue.createElementForPropertyPreview(cellProperty);
                }
                rows.push([rowProperty.name, rowValue]);
            }
        }

        // If there were valuePreviews, convert to a flat list.
        if (rows.length) {
            columnNames.unshift(WI.UIString("(Index)"));
            for (var i = 0; i < rows.length; ++i) {
                var rowName = rows[i][0];
                var rowValue = rows[i][1];
                flatValues.push(rowName);
                for (var j = 1; j < columnNames.length; ++j) {
                    var columnName = columnNames[j];
                    if (!(columnName in rowValue))
                        flatValues.push(emDash);
                    else
                        flatValues.push(rowValue[columnName]);
                }
            }
        }

        // If there were no value Previews, then check for an array of values.
        if (!flatValues.length && preview.propertyPreviews) {
            for (var i = 0; i < preview.propertyPreviews.length; ++i) {
                var rowProperty = preview.propertyPreviews[i];
                if (!("value" in rowProperty))
                    continue;

                if (!columnNames.length) {
                    columnNames.push(WI.UIString("Index"));
                    columnNames.push(WI.UIString("Value"));
                }

                flatValues.push(rowProperty.name);
                flatValues.push(WI.FormattedValue.createElementForPropertyPreview(rowProperty));
            }
        }

        // If no table data show nothing.
        if (!flatValues.length)
            return element;

        // FIXME: Should we output something extra if the preview is lossless?

        var dataGrid = WI.DataGrid.createSortableDataGrid(columnNames, flatValues);
        dataGrid.inline = true;
        dataGrid.variableHeightRows = true;

        element.appendChild(dataGrid.element);

        dataGrid.updateLayoutIfNeeded();

        return element;
    }

    _levelString()
    {
        switch (this._message.level) {
        case WI.ConsoleMessage.MessageLevel.Log:
            return "Log";
        case WI.ConsoleMessage.MessageLevel.Info:
            return "Info";
        case WI.ConsoleMessage.MessageLevel.Warning:
            return "Warning";
        case WI.ConsoleMessage.MessageLevel.Debug:
            return "Debug";
        case WI.ConsoleMessage.MessageLevel.Error:
            return "Error";
        }
    }

    _enforcesClipboardPrefixString()
    {
        return this._message.type !== WI.ConsoleMessage.MessageType.Result;
    }

    _clipboardPrefixString()
    {
        if (this._message.type === WI.ConsoleMessage.MessageType.Result)
            return "< ";

        return "[" + this._levelString() + "] ";
    }

    _makeExpandable()
    {
        if (this._expandable)
            return;

        this._expandable = true;

        this._element.classList.add("expandable");

        this._boundClickHandler = this.toggle.bind(this);
        this._messageBodyElement.addEventListener("click", this._boundClickHandler);
    }

    _handleContextMenu(event)
    {
        let image = event.target.closest(".console-image > .console-message-body > img");
        if (!image)
            return;

        let contextMenu = WI.ContextMenu.createFromEvent(event);

        contextMenu.appendItem(WI.UIString("Save Image"), () => {
            const forceSaveAs = true;
            WI.FileUtilities.save({
                url: WI.FileUtilities.inspectorURLForFilename(image.getAttribute("filename")),
                content: parseDataURL(this._message.messageText).data,
                base64Encoded: true,
            }, forceSaveAs);
        });

        contextMenu.appendSeparator();
    }
};
