/*
 * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

// FIXME: <https://webkit.org/b/143545> Web Inspector: LogContentView should use higher level objects

WI.LogContentView = class LogContentView extends WI.ContentView
{
    constructor(representedObject)
    {
        super(representedObject);

        this._nestingLevel = 0;
        this._selectedMessages = [];
        this._immediatelyHiddenMessages = new Set;

        // FIXME: Try to use a marker, instead of a list of messages that get re-added.
        this._provisionalMessages = [];

        this.element.classList.add("log");

        this.messagesElement = document.createElement("div");
        this.messagesElement.classList.add("console-messages");
        this.messagesElement.tabIndex = 0;
        this.messagesElement.setAttribute("role", "log");
        this.messagesElement.addEventListener("mousedown", this._mousedown.bind(this));
        this.messagesElement.addEventListener("keydown", this._keyDown.bind(this));
        this.messagesElement.addEventListener("keypress", this._keyPress.bind(this));
        this.messagesElement.addEventListener("dragstart", this._ondragstart.bind(this), true);
        this.messagesElement.addEventListener("dragover", this._handleDragOver.bind(this));
        this.messagesElement.addEventListener("drop", this._handleDrop.bind(this));
        this.element.appendChild(this.messagesElement);

        this.prompt = WI.quickConsole.prompt;

        this._keyboardShortcutCommandA = new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.CommandOrControl, "A");
        this._keyboardShortcutEsc = new WI.KeyboardShortcut(null, WI.KeyboardShortcut.Key.Escape);

        this._logViewController = new WI.JavaScriptLogViewController(this.messagesElement, this.messagesElement, this.prompt, this, "console-prompt-history");
        this._lastMessageView = null;

        const fixed = true;
        this._findBanner = new WI.FindBanner(this, "console-find-banner", fixed);
        this._findBanner.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
        this._findBanner.targetElement = this.element;

        this._currentSearchQuery = "";
        this._searchMatches = [];
        this._selectedSearchMatch = null;
        this._selectedSearchMatchIsValid = false;

        this._preserveLogNavigationItem = new WI.CheckboxNavigationItem("preserve-log", WI.UIString("Preserve Log"), !WI.settings.clearLogOnNavigate.value);
        this._preserveLogNavigationItem.tooltip = WI.UIString("Do not clear the console on new page loads");
        this._preserveLogNavigationItem.addEventListener(WI.CheckboxNavigationItem.Event.CheckedDidChange, () => {
            WI.settings.clearLogOnNavigate.value = !WI.settings.clearLogOnNavigate.value;
        });
        WI.settings.clearLogOnNavigate.addEventListener(WI.Setting.Event.Changed, this._handleClearLogOnNavigateSettingChanged, this);

        this._emulateInUserGestureNavigationItem = new WI.CheckboxNavigationItem("emulate-in-user-gesture", WI.UIString("Emulate User Gesture"), WI.settings.emulateInUserGesture.value);
        this._emulateInUserGestureNavigationItem.tooltip = WI.UIString("Run console commands as if inside a user gesture");
        this._emulateInUserGestureNavigationItem.addEventListener(WI.CheckboxNavigationItem.Event.CheckedDidChange, () => {
            WI.settings.emulateInUserGesture.value = !WI.settings.emulateInUserGesture.value;
        });
        WI.settings.emulateInUserGesture.addEventListener(WI.Setting.Event.Changed, this._handleEmulateInUserGestureSettingChanged, this);

        this._checkboxesNavigationItemGroup = new WI.GroupNavigationItem([this._preserveLogNavigationItem, this._emulateInUserGestureNavigationItem, new WI.DividerNavigationItem]);

        let scopeBarItems = [
            new WI.ScopeBarItem(WI.LogContentView.Scopes.All, WI.UIString("All"), {exclusive: true}),
            new WI.ScopeBarItem(WI.LogContentView.Scopes.Evaluations, WI.UIString("Evaluations"), {className: "evaluations"}),
            new WI.ScopeBarItem(WI.LogContentView.Scopes.Errors, WI.UIString("Errors"), {className: "errors"}),
            new WI.ScopeBarItem(WI.LogContentView.Scopes.Warnings, WI.UIString("Warnings"), {className: "warnings"}),
            new WI.ScopeBarItem(WI.LogContentView.Scopes.Logs, WI.UIString("Logs"), {className: "logs"}),
            new WI.ScopeBarItem(WI.LogContentView.Scopes.Infos, WI.UIString("Infos"), {className: "infos", hidden: true}),
            new WI.ScopeBarItem(WI.LogContentView.Scopes.Debugs, WI.UIString("Debugs"), {className: "debugs", hidden: true}),
        ];
        this._scopeBar = new WI.ScopeBar("log-scope-bar", scopeBarItems, scopeBarItems[0]);
        this._scopeBar.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
        this._scopeBar.addEventListener(WI.ScopeBar.Event.SelectionChanged, this._scopeBarSelectionDidChange, this);

        this._hasNonDefaultLogChannelMessage = false;
        if (WI.ConsoleManager.supportsLogChannels()) {
            let messageChannelBarItems = [
                new WI.ScopeBarItem(WI.LogContentView.Scopes.AllChannels, WI.UIString("All"), {exclusive: true}),
                new WI.ScopeBarItem(WI.LogContentView.Scopes.Media, WI.UIString("Media"), {className: "media"}),
                new WI.ScopeBarItem(WI.LogContentView.Scopes.MediaSource, WI.UIString("MediaSource"), {className: "mediasource"}),
                new WI.ScopeBarItem(WI.LogContentView.Scopes.WebRTC, WI.UIString("WebRTC"), {className: "webrtc"}),
            ];

            this._messageSourceBar = new WI.ScopeBar("message-channel-scope-bar", messageChannelBarItems, messageChannelBarItems[0]);
            this._messageSourceBar.addEventListener(WI.ScopeBar.Event.SelectionChanged, this._messageSourceBarSelectionDidChange, this);
        }

        this._garbageCollectNavigationItem = new WI.ButtonNavigationItem("garbage-collect", WI.UIString("Collect garbage"), "Images/NavigationItemGarbageCollect.svg", 16, 16);
        this._garbageCollectNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._garbageCollect, this);

        this._clearLogNavigationItem = new WI.ButtonNavigationItem("clear-log", WI.UIString("Clear log (%s or %s)").format(WI.clearKeyboardShortcut.displayName, this._logViewController.messagesAlternateClearKeyboardShortcut.displayName), "Images/NavigationItemTrash.svg", 15, 15);
        this._clearLogNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.High;
        this._clearLogNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._clearLog, this);

        this._showConsoleTabNavigationItem = new WI.ButtonNavigationItem("show-tab", WI.UIString("Show Console tab"), "Images/SplitToggleUp.svg", 16, 16);
        this._showConsoleTabNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.High;
        this._showConsoleTabNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._showConsoleTab, this);

        this.messagesElement.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), false);

        WI.consoleManager.addEventListener(WI.ConsoleManager.Event.SessionStarted, this._sessionStarted, this);
        WI.consoleManager.addEventListener(WI.ConsoleManager.Event.MessageAdded, this._messageAdded, this);
        WI.consoleManager.addEventListener(WI.ConsoleManager.Event.PreviousMessageRepeatCountUpdated, this._previousMessageRepeatCountUpdated, this);
        WI.consoleManager.addEventListener(WI.ConsoleManager.Event.Cleared, this._logCleared, this);

        WI.Frame.addEventListener(WI.Frame.Event.ProvisionalLoadStarted, this._provisionalLoadStarted, this);
    }

    // Public

    get navigationItems()
    {
        let navigationItems = [
            this._findBanner,
            this._checkboxesNavigationItemGroup,
            new WI.DividerNavigationItem,
            this._scopeBar,
            new WI.DividerNavigationItem
        ];

        if (this._hasNonDefaultLogChannelMessage && this._messageSourceBar)
            navigationItems.push(this._messageSourceBar, new WI.DividerNavigationItem);

        if (InspectorBackend.hasCommand("Heap.gc"))
            navigationItems.push(this._garbageCollectNavigationItem);

        navigationItems.push(this._clearLogNavigationItem);

        if (WI.isShowingSplitConsole())
            navigationItems.push(new WI.DividerNavigationItem, this._showConsoleTabNavigationItem);

        return navigationItems;
    }

    get scopeBar()
    {
        return this._scopeBar;
    }

    get logViewController()
    {
        return this._logViewController;
    }

    get scrollableElements()
    {
        return [this.messagesElement];
    }

    get shouldKeepElementsScrolledToBottom()
    {
        return true;
    }

    shown()
    {
        super.shown();

        this._logViewController.renderPendingMessages();
    }

    closed()
    {
        // While it may be possible to get here, this is a singleton ContentView instance
        // that is often re-inserted back into different ContentBrowsers, so we shouldn't
        // remove the event listeners. The singleton will never go away anyways.
        console.assert(this === WI.consoleContentView);

        super.closed();
    }

    didAppendConsoleMessageView(messageView)
    {
        console.assert(messageView instanceof WI.ConsoleMessageView || messageView instanceof WI.ConsoleCommandView);

        // Nest the message.
        var type = messageView instanceof WI.ConsoleCommandView ? null : messageView.message.type;
        if (this._nestingLevel && type !== WI.ConsoleMessage.MessageType.EndGroup) {
            var x = 16 * this._nestingLevel;
            var messageElement = messageView.element;
            messageElement.style.left = x + "px";
            messageElement.style.width = "calc(100% - " + x + "px)";
        }

        // Update the nesting level.
        switch (type) {
        case WI.ConsoleMessage.MessageType.StartGroup:
        case WI.ConsoleMessage.MessageType.StartGroupCollapsed:
            ++this._nestingLevel;
            break;
        case WI.ConsoleMessage.MessageType.EndGroup:
            if (this._nestingLevel > 0)
                --this._nestingLevel;
            break;
        }

        this._clearFocusableChildren();

        // Some results don't populate until further backend dispatches occur (like the DOM tree).
        // We want to remove focusable children after those pending dispatches too.
        let target = messageView.message ? messageView.message.target : WI.runtimeManager.activeExecutionContext.target;
        target.connection.runAfterPendingDispatches(this._clearFocusableChildren.bind(this));

        if (!this._scopeBar.item(WI.LogContentView.Scopes.All).selected) {
            if (messageView instanceof WI.ConsoleCommandView || messageView.message instanceof WI.ConsoleCommandResultMessage)
                this._scopeBar.item(WI.LogContentView.Scopes.Evaluations).toggle(true, {extendSelection: true});
        }

        console.assert(messageView.element instanceof Element);
        this._filterMessageElements([messageView.element]);

        if (!this._isMessageVisible(messageView.element)) {
            this._immediatelyHiddenMessages.add(messageView);
            this._showHiddenMessagesBannerIfNeeded();
        }

        this._lastMessageView = messageView;
    }

    get supportsSearch() { return true; }
    get numberOfSearchResults() { return this.hasPerformedSearch ? this._searchMatches.length : null; }
    get hasPerformedSearch() { return this._currentSearchQuery !== ""; }

    get supportsCustomFindBanner()
    {
        return true;
    }

    showCustomFindBanner()
    {
        if (!this.visible)
            return;

        this._findBanner.focus();
    }

    get supportsSave()
    {
        if (!this.visible)
            return false;

        if (WI.isShowingSplitConsole())
            return false;

        return true;
    }

    get saveData()
    {
        return {
            content: this._formatMessagesAsData(false),
            suggestedName: WI.UIString("Console") + ".txt",
            forceSaveAs: true,
        };
    }

    handleCopyEvent(event)
    {
        if (!this._selectedMessages.length)
            return;

        event.clipboardData.setData("text/plain", this._formatMessagesAsData(true));
        event.stopPropagation();
        event.preventDefault();
    }

    handleClearShortcut(event)
    {
        this._logViewController.requestClearMessages();
    }

    handlePopulateFindShortcut()
    {
        let searchQuery = this.searchQueryWithSelection();
        if (!searchQuery)
            return;

        this._findBanner.searchQuery = searchQuery;

        this.performSearch(this._findBanner.searchQuery);
    }

    handleFindNextShortcut()
    {
        this.findBannerRevealNextResult(this._findBanner);
    }

    handleFindPreviousShortcut()
    {
        this.findBannerRevealPreviousResult(this._findBanner);
    }

    findBannerRevealPreviousResult()
    {
        this.highlightPreviousSearchMatch();
    }

    highlightPreviousSearchMatch()
    {
        if (!this.hasPerformedSearch || isEmptyObject(this._searchMatches))
            return;

        var index = this._selectedSearchMatch ? this._searchMatches.indexOf(this._selectedSearchMatch) : this._searchMatches.length;
        this._highlightSearchMatchAtIndex(index - 1);
    }

    findBannerRevealNextResult()
    {
        this.highlightNextSearchMatch();
    }

    highlightNextSearchMatch()
    {
        if (!this.hasPerformedSearch || isEmptyObject(this._searchMatches))
            return;

        var index = this._selectedSearchMatch ? this._searchMatches.indexOf(this._selectedSearchMatch) + 1 : 0;
        this._highlightSearchMatchAtIndex(index);
    }

    findBannerWantsToClearAndBlur(findBanner)
    {
        if (this._selectedMessages.length)
            this.messagesElement.focus();
        else
            this.prompt.focus();
    }

    // Private

    _formatMessagesAsData(onlySelected)
    {
        var messages = this._allMessageElements();

        if (onlySelected) {
            messages = messages.filter(function(message) {
                return message.classList.contains(WI.LogContentView.SelectedStyleClassName);
            });
        }

        var data = "";

        var isPrefixOptional = messages.length <= 1 && onlySelected;
        messages.forEach(function(messageElement, index) {
            var messageView = messageElement.__messageView || messageElement.__commandView;
            if (!messageView)
                return;

            if (index > 0)
                data += "\n";
            data += messageView.toClipboardString(isPrefixOptional);
        });

        return data;
    }

    _sessionStarted(event)
    {
        if (WI.settings.clearLogOnNavigate.value) {
            this._reappendProvisionalMessages();
            return;
        }

        for (let messageElement of this._allMessageElements()) {
            if (messageElement.__messageView)
                messageElement.__messageView.clearSessionState();
        }

        const isFirstSession = false;
        const newSessionReason = event.data.wasReloaded ? WI.ConsoleSession.NewSessionReason.PageReloaded : WI.ConsoleSession.NewSessionReason.PageNavigated;
        this._logViewController.startNewSession(isFirstSession, {newSessionReason, timestamp: event.data.timestamp});

        this._clearProvisionalState();
    }

    _scopeFromMessageSource(source)
    {
        switch (source) {
        case WI.ConsoleMessage.MessageSource.Media:
            return WI.LogContentView.Scopes.Media;
        case WI.ConsoleMessage.MessageSource.WebRTC:
            return WI.LogContentView.Scopes.WebRTC;
        case WI.ConsoleMessage.MessageSource.MediaSource:
            return WI.LogContentView.Scopes.MediaSource;
        }

        return undefined;
    }

    _scopeFromMessageLevel(level)
    {
        switch (level) {
        case WI.ConsoleMessage.MessageLevel.Warning:
            return WI.LogContentView.Scopes.Warnings;
        case WI.ConsoleMessage.MessageLevel.Error:
            return WI.LogContentView.Scopes.Errors;
        case WI.ConsoleMessage.MessageLevel.Log:
            return WI.LogContentView.Scopes.Logs;
        case WI.ConsoleMessage.MessageLevel.Info:
            return this._hasNonDefaultLogChannelMessage ? WI.LogContentView.Scopes.Infos : WI.LogContentView.Scopes.Logs;
        case WI.ConsoleMessage.MessageLevel.Debug:
            return this._hasNonDefaultLogChannelMessage ? WI.LogContentView.Scopes.Debugs : WI.LogContentView.Scopes.Logs;
        }
        console.assert(false, "This should not be reached.");

        return undefined;
    }

    _messageAdded(event)
    {
        let message = event.data.message;
        if (this._startedProvisionalLoad)
            this._provisionalMessages.push(message);

        if (!this._hasNonDefaultLogChannelMessage && WI.consoleManager.logChannelSources.includes(message.source)) {
            this._hasNonDefaultLogChannelMessage = true;
            this.dispatchEventToListeners(WI.ContentView.Event.NavigationItemsDidChange);
            this._scopeBar.item(WI.LogContentView.Scopes.Infos).hidden = false;
            this._scopeBar.item(WI.LogContentView.Scopes.Debugs).hidden = false;
        }

        this._logViewController.appendConsoleMessage(message);
    }

    _previousMessageRepeatCountUpdated(event)
    {
        if (!this._logViewController.updatePreviousMessageRepeatCount(event.data.count))
            return;

        if (this._lastMessageView) {
            if (this._isMessageVisible(this._lastMessageView.element))
                return;

            this._immediatelyHiddenMessages.add(this._lastMessageView);
        }

        this._showHiddenMessagesBannerIfNeeded();
    }

    _handleContextMenuEvent(event)
    {
        if (!window.getSelection().isCollapsed) {
            // If there is a selection, we want to show our normal context menu
            // (with Copy, etc.), and not Clear Log.
            return;
        }

        // In the case that there are selected messages, only clear that selection if the right-click
        // is not on the element or descendants of the selected messages.
        if (this._selectedMessages.length && !this._selectedMessages.some(element => element.contains(event.target))) {
            this._clearMessagesSelection();
            this._mousedown(event);
        }

        // If there are no selected messages, right-clicking will not reset the current mouse state
        // meaning that when the context menu is dismissed, console messages will be selected when
        // the user moves the mouse even though no buttons are pressed.
        if (!this._selectedMessages.length)
            this._mouseup(event);

        // We don't want to show the custom menu for links in the console.
        if (event.target.closest("a"))
            return;

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

        contextMenu.appendSeparator();

        if (this._selectedMessages.length) {
            contextMenu.appendItem(WI.UIString("Copy Selected"), () => {
                InspectorFrontendHost.copyText(this._formatMessagesAsData(true));
            });

            contextMenu.appendItem(WI.UIString("Save Selected"), () => {
                const forceSaveAs = true;
                WI.FileUtilities.save({
                    content: this._formatMessagesAsData(true),
                    suggestedName: WI.UIString("Console") + ".txt",
                }, forceSaveAs);
            });

            contextMenu.appendSeparator();
        }

        contextMenu.appendItem(WI.UIString("Clear Log"), this._clearLog.bind(this));
        contextMenu.appendSeparator();
    }

    _mousedown(event)
    {
        if (this._selectedMessages.length && (event.button !== 0 || event.ctrlKey))
            return;

        if (event.defaultPrevented) {
            // Default was prevented on the event, so this means something deeper (like a disclosure triangle)
            // handled the mouse down. In this case we want to clear the selection and don't make a new selection.
            this._clearMessagesSelection();
            return;
        }

        this._mouseDownWrapper = event.target.closest("." + WI.LogContentView.ItemWrapperStyleClassName);
        this._mouseDownShiftKey = event.shiftKey;
        this._mouseDownCommandKey = event.metaKey;
        this._mouseMoveIsRowSelection = false;

        window.addEventListener("mousemove", this);
        window.addEventListener("mouseup", this);
    }

    _targetInMessageCanBeSelected(target, message)
    {
        if (target.closest("a"))
            return false;
        return true;
    }

    _mousemove(event)
    {
        var selection = window.getSelection();
        var wrapper = event.target.closest("." + WI.LogContentView.ItemWrapperStyleClassName);

        if (!wrapper) {
            // No wrapper under the mouse, so look at the selection to try and find one.
            if (!selection.isCollapsed) {
                let focusElement = selection.focusNode;
                if (!(focusElement instanceof Element))
                    focusElement = focusElement.parentElement;
                wrapper = focusElement.closest("." + WI.LogContentView.ItemWrapperStyleClassName);
            }

            if (!wrapper) {
                selection.removeAllRanges();
                return;
            }
        }

        if (!selection.isCollapsed)
            this._clearMessagesSelection();

        if (wrapper === this._mouseDownWrapper && !this._mouseMoveIsRowSelection)
            return;

        // Don't change the selection if the mouse has moved outside of the view (e.g. for faster scrolling).
        if (!this.element.contains(event.target))
            return;

        selection.removeAllRanges();

        if (!this._mouseMoveIsRowSelection)
            this._updateMessagesSelection(this._mouseDownWrapper, this._mouseDownCommandKey, this._mouseDownShiftKey, false);

        this._updateMessagesSelection(wrapper, false, true, false);

        this._mouseMoveIsRowSelection = true;

        event.preventDefault();
        event.stopPropagation();
    }

    _mouseup(event)
    {
        window.removeEventListener("mousemove", this);
        window.removeEventListener("mouseup", this);

        var selection = window.getSelection();
        var wrapper = event.target.closest("." + WI.LogContentView.ItemWrapperStyleClassName);

        if (wrapper && (selection.isCollapsed || event.shiftKey)) {
            selection.removeAllRanges();

            if (this._targetInMessageCanBeSelected(event.target, wrapper)) {
                var sameWrapper = wrapper === this._mouseDownWrapper;
                this._updateMessagesSelection(wrapper, sameWrapper ? this._mouseDownCommandKey : false, sameWrapper ? this._mouseDownShiftKey : true, false);
            }
        } else if (!selection.isCollapsed) {
            // There is a text selection, clear the row selection.
            this._clearMessagesSelection();
        } else if (!this._mouseDownWrapper) {
            // The mouse didn't hit a console item, so clear the row selection.
            this._clearMessagesSelection();

            // Focus the prompt. Focusing the prompt needs to happen after the click to work.
            setTimeout(() => { this.prompt.focus(); }, 0);
        }

        delete this._mouseMoveIsRowSelection;
        delete this._mouseDownWrapper;
        delete this._mouseDownShiftKey;
        delete this._mouseDownCommandKey;
    }

    _ondragstart(event)
    {
        if (event.target.closest("." + WI.DOMTreeOutline.StyleClassName)) {
            event.stopPropagation();
            event.preventDefault();
        }
    }

    _handleDragOver(event)
    {
        if (event.dataTransfer.types.includes(WI.DOMTreeOutline.DOMNodeIdDragType)) {
            event.preventDefault();
            event.dataTransfer.dropEffect = "copy";
        }
    }

    _handleDrop(event)
    {
        let domNodeId = event.dataTransfer.getData(WI.DOMTreeOutline.DOMNodeIdDragType);
        if (domNodeId) {
            event.preventDefault();

            let domNode = WI.domManager.nodeForId(domNodeId);
            WI.RemoteObject.resolveNode(domNode, WI.RuntimeManager.ConsoleObjectGroup)
            .then((remoteObject) => {
                let text = domNode.nodeType() === Node.ELEMENT_NODE ? WI.UIString("Dropped Element") : WI.UIString("Dropped Node");
                const addSpecialUserLogClass = true;
                WI.consoleLogViewController.appendImmediateExecutionWithResult(text, remoteObject, addSpecialUserLogClass);

                this.prompt.focus();
            });
        }
    }

    handleEvent(event)
    {
        switch (event.type) {
        case "mousemove":
            this._mousemove(event);
            break;
        case "mouseup":
            this._mouseup(event);
            break;
        }
    }

    _updateMessagesSelection(message, multipleSelection, rangeSelection, shouldScrollIntoView)
    {
        console.assert(message);
        if (!message)
            return;

        var alreadySelectedMessage = this._selectedMessages.includes(message);
        if (alreadySelectedMessage && this._selectedMessages.length && multipleSelection) {
            message.classList.remove(WI.LogContentView.SelectedStyleClassName);
            this._selectedMessages.remove(message);
            return;
        }

        if (!multipleSelection && !rangeSelection)
            this._clearMessagesSelection();

        if (rangeSelection) {
            var messages = this._visibleMessageElements();

            var refIndex = this._referenceMessageForRangeSelection ? messages.indexOf(this._referenceMessageForRangeSelection) : 0;
            var targetIndex = messages.indexOf(message);

            var newRange = [Math.min(refIndex, targetIndex), Math.max(refIndex, targetIndex)];

            if (this._selectionRange && this._selectionRange[0] === newRange[0] && this._selectionRange[1] === newRange[1])
                return;

            var startIndex = this._selectionRange ? Math.min(this._selectionRange[0], newRange[0]) : newRange[0];
            var endIndex = this._selectionRange ? Math.max(this._selectionRange[1], newRange[1]) : newRange[1];

            for (var i = startIndex; i <= endIndex; ++i) {
                var messageInRange = messages[i];
                if (i >= newRange[0] && i <= newRange[1] && !messageInRange.classList.contains(WI.LogContentView.SelectedStyleClassName)) {
                    messageInRange.classList.add(WI.LogContentView.SelectedStyleClassName);
                    this._selectedMessages.push(messageInRange);
                } else if (i < newRange[0] || i > newRange[1] && messageInRange.classList.contains(WI.LogContentView.SelectedStyleClassName)) {
                    messageInRange.classList.remove(WI.LogContentView.SelectedStyleClassName);
                    this._selectedMessages.remove(messageInRange);
                }
            }

            this._selectionRange = newRange;
        } else {
            message.classList.add(WI.LogContentView.SelectedStyleClassName);
            this._selectedMessages.push(message);
            this._selectionRange = null;
        }

        if (!rangeSelection)
            this._referenceMessageForRangeSelection = message;

        if (shouldScrollIntoView && !alreadySelectedMessage) {
            let lastMessage = this._selectedMessages.lastValue;
            if (lastMessage)
                lastMessage.scrollIntoViewIfNeeded();
        }
    }

    _isMessageVisible(message)
    {
        var node = message;

        if (node.classList.contains(WI.LogContentView.FilteredOutStyleClassName))
            return false;

        if (this.hasPerformedSearch && node.classList.contains(WI.LogContentView.FilteredOutBySearchStyleClassName))
            return false;

        if (message.classList.contains("console-group-title"))
            node = node.parentNode.parentNode;

        while (node && node !== this.messagesElement) {
            if (node.classList.contains("collapsed"))
                return false;
            node = node.parentNode;
        }

        return true;
    }

    _isMessageSelected(message)
    {
        return message.classList.contains(WI.LogContentView.SelectedStyleClassName);
    }

    _clearMessagesSelection()
    {
        this._selectedMessages.forEach(function(message) {
            message.classList.remove(WI.LogContentView.SelectedStyleClassName);
        });
        this._selectedMessages = [];
        delete this._referenceMessageForRangeSelection;
    }

    _selectAllMessages()
    {
        this._clearMessagesSelection();

        var messages = this._visibleMessageElements();
        for (var i = 0; i < messages.length; ++i) {
            var message = messages[i];
            message.classList.add(WI.LogContentView.SelectedStyleClassName);
            this._selectedMessages.push(message);
        }
    }

    _allMessageElements()
    {
        return Array.from(this.messagesElement.querySelectorAll(".console-message, .console-user-command"));
    }

    _unfilteredMessageElements()
    {
        return this._allMessageElements().filter(function(message) {
            return !message.classList.contains(WI.LogContentView.FilteredOutStyleClassName);
        });
    }

    _visibleMessageElements()
    {
        var unfilteredMessages = this._unfilteredMessageElements();

        if (!this.hasPerformedSearch)
            return unfilteredMessages;

        return unfilteredMessages.filter(function(message) {
            return !message.classList.contains(WI.LogContentView.FilteredOutBySearchStyleClassName);
        });
    }

    _logCleared(event)
    {
        for (let messageElement of this._allMessageElements()) {
            if (messageElement.__messageView)
                messageElement.__messageView.clearSessionState();
        }

        this._logViewController.clear();

        this._nestingLevel = 0;
        this._selectedMessages = [];
        this._immediatelyHiddenMessages.clear();

        if (this._currentSearchQuery)
            this.performSearch(this._currentSearchQuery);

        this._showHiddenMessagesBannerIfNeeded();
    }

    _showConsoleTab()
    {
        const requestedScope = null;
        WI.showConsoleTab(requestedScope, {
            initiatorHint: WI.TabBrowser.TabNavigationInitiator.ButtonClick,
        });
    }

    _clearLog()
    {
        WI.consoleManager.requestClearMessages();
    }

    _garbageCollect()
    {
        // COMPATIBILITY (iOS 10.3): Worker targets did not support Heap.gc.
        for (let target of WI.targets) {
            if (target.hasDomain("Heap"))
                target.HeapAgent.gc();
        }
    }

    _messageShouldBeVisible(message)
    {
        let messageSource = this._messageSourceBar && this._scopeFromMessageSource(message.source);
        if (messageSource && !this._messageSourceBar.item(messageSource).selected && !this._messageSourceBar.item(WI.LogContentView.Scopes.AllChannels).selected)
            return false;

        let messageLevel = this._scopeFromMessageLevel(message.level);
        if (messageLevel)
            return this._scopeBar.item(messageLevel).selected || this._scopeBar.item(WI.LogContentView.Scopes.All).selected;

        return true;
    }

    _messageSourceBarSelectionDidChange(event)
    {
        let items = this._messageSourceBar.selectedItems;
        if (items.some((item) => item.id === WI.LogContentView.Scopes.AllChannels))
            items = this._messageSourceBar.items;

        this._filterMessageElements(this._allMessageElements());

        this._showHiddenMessagesBannerIfNeeded();
    }

    _scopeBarSelectionDidChange(event)
    {
        let items = this._scopeBar.selectedItems;
        if (items.some((item) => item.id === WI.LogContentView.Scopes.All))
            items = this._scopeBar.items;

        this._filterMessageElements(this._allMessageElements());

        this._showHiddenMessagesBannerIfNeeded();
    }

    _filterMessageElements(messageElements)
    {
        messageElements.forEach(function(messageElement) {
            let visible = false;
            if (messageElement.__commandView instanceof WI.ConsoleCommandView || messageElement.__message instanceof WI.ConsoleCommandResultMessage)
                visible = this._scopeBar.selectedItems.some((item) => item.id === WI.LogContentView.Scopes.Evaluations || item.id === WI.LogContentView.Scopes.All);
            else
                visible = this._messageShouldBeVisible(messageElement.__message);

            let classList = messageElement.classList;
            if (visible) {
                classList.remove(WI.LogContentView.FilteredOutStyleClassName);
                this._immediatelyHiddenMessages.delete(messageElement.__messageView);
            } else {
                this._selectedMessages.remove(messageElement);
                classList.remove(WI.LogContentView.SelectedStyleClassName);
                classList.add(WI.LogContentView.FilteredOutStyleClassName);
            }
        }, this);

        this.performSearch(this._currentSearchQuery);
    }

    _handleClearLogOnNavigateSettingChanged()
    {
        this._preserveLogNavigationItem.checked = !WI.settings.clearLogOnNavigate.value;
    }

    _handleEmulateInUserGestureSettingChanged()
    {
        this._emulateInUserGestureNavigationItem.checked = WI.settings.emulateInUserGesture.value;
    }

    _keyDown(event)
    {
        if (this._keyboardShortcutCommandA.matchesEvent(event))
            this._commandAWasPressed(event);
        else if (this._keyboardShortcutEsc.matchesEvent(event))
            this._escapeWasPressed(event);
        else if (event.keyIdentifier === "Up")
            this._upArrowWasPressed(event);
        else if (event.keyIdentifier === "Down")
            this._downArrowWasPressed(event);
        else if (event.keyIdentifier === "Left")
            this._leftArrowWasPressed(event);
        else if (event.keyIdentifier === "Right")
            this._rightArrowWasPressed(event);
        else if (event.keyIdentifier === "Enter" && event.metaKey)
            this._commandEnterWasPressed(event);
    }

    _keyPress(event)
    {
        const isCommandC = event.metaKey && event.keyCode === 99;
        if (!isCommandC)
            this.prompt.focus();
    }

    _commandAWasPressed(event)
    {
        this._selectAllMessages();
        event.preventDefault();
    }

    _escapeWasPressed(event)
    {
        if (this._selectedMessages.length)
            this._clearMessagesSelection();
        else
            this.prompt.focus();

        event.preventDefault();
    }

    _upArrowWasPressed(event)
    {
        var messages = this._visibleMessageElements();

        if (!this._selectedMessages.length) {
            if (messages.length)
                this._updateMessagesSelection(messages.lastValue, false, false, true);
            return;
        }

        var lastMessage = this._selectedMessages.lastValue;
        var previousMessage = this._previousMessage(lastMessage);
        if (previousMessage) {
            this._updateMessagesSelection(previousMessage, false, event.shiftKey, true);
            event.preventDefault();
        } else if (!event.shiftKey) {
            this._clearMessagesSelection();
            if (messages.length) {
                this._updateMessagesSelection(messages[0], false, false, true);
                event.preventDefault();
            }
        }
    }

    _downArrowWasPressed(event)
    {
        var messages = this._visibleMessageElements();

        if (!this._selectedMessages.length) {
            if (messages.length)
                this._updateMessagesSelection(messages[0], false, false, true);
            return;
        }

        var lastMessage = this._selectedMessages.lastValue;
        var nextMessage = this._nextMessage(lastMessage);
        if (nextMessage) {
            this._updateMessagesSelection(nextMessage, false, event.shiftKey, true);
            event.preventDefault();
        } else if (!event.shiftKey) {
            this._clearMessagesSelection();
            if (messages.length) {
                this._updateMessagesSelection(messages.lastValue, false, false, true);
                event.preventDefault();
            }
        }
    }

    _leftArrowWasPressed(event)
    {
        if (this._selectedMessages.length !== 1)
            return;

        var currentMessage = this._selectedMessages[0];
        if (currentMessage.classList.contains("console-group-title")) {
            currentMessage.parentNode.classList.add("collapsed");
            event.preventDefault();
        } else if (currentMessage.__messageView && currentMessage.__messageView.expandable) {
            currentMessage.__messageView.collapse();
            event.preventDefault();
        }
    }

    _rightArrowWasPressed(event)
    {
        if (this._selectedMessages.length !== 1)
            return;

        var currentMessage = this._selectedMessages[0];
        if (currentMessage.classList.contains("console-group-title")) {
            currentMessage.parentNode.classList.remove("collapsed");
            event.preventDefault();
        } else if (currentMessage.__messageView && currentMessage.__messageView.expandable) {
            currentMessage.__messageView.expand();
            event.preventDefault();
        }
    }

    _commandEnterWasPressed(event)
    {
        if (this._selectedMessages.length !== 1)
            return;

        let message = this._selectedMessages[0];
        if (message.__commandView && message.__commandView.commandText) {
            this._logViewController.consolePromptTextCommitted(null, message.__commandView.commandText);
            event.preventDefault();
        }
    }

    _previousMessage(message)
    {
        var messages = this._visibleMessageElements();
        for (var i = messages.indexOf(message) - 1; i >= 0; --i) {
            if (this._isMessageVisible(messages[i]))
                return messages[i];
        }
        return null;
    }

    _nextMessage(message)
    {
        var messages = this._visibleMessageElements();
        for (var i = messages.indexOf(message) + 1; i < messages.length; ++i) {
            if (this._isMessageVisible(messages[i]))
                return messages[i];
        }
        return null;
    }

    _clearFocusableChildren()
    {
        var focusableElements = this.messagesElement.querySelectorAll("[tabindex]");
        for (var i = 0, count = focusableElements.length; i < count; ++i)
            focusableElements[i].removeAttribute("tabindex");
    }

    findBannerPerformSearch(findBanner, searchQuery)
    {
        this.performSearch(searchQuery);
    }

    findBannerSearchCleared()
    {
        this.searchCleared();
    }

    revealNextSearchResult()
    {
        this.findBannerRevealNextResult();
    }

    revealPreviousSearchResult()
    {
        this.findBannerRevealPreviousResult();
    }

    performSearch(searchQuery)
    {
        if (!isEmptyObject(this._searchHighlightDOMChanges))
            WI.revertDOMChanges(this._searchHighlightDOMChanges);

        this._currentSearchQuery = searchQuery;
        this._searchHighlightDOMChanges = [];
        this._searchMatches = [];
        this._selectedSearchMatchIsValid = false;
        this._selectedSearchMatch = null;
        let numberOfResults = 0;

        if (this._currentSearchQuery === "") {
            this.element.classList.remove(WI.LogContentView.SearchInProgressStyleClassName);
            this.dispatchEventToListeners(WI.ContentView.Event.NumberOfSearchResultsDidChange);
            return;
        }

        this.element.classList.add(WI.LogContentView.SearchInProgressStyleClassName);

        let searchRegex = WI.SearchUtilities.regExpForString(this._currentSearchQuery, WI.SearchUtilities.defaultSettings);
        this._unfilteredMessageElements().forEach(function(message) {
            let matchRanges = [];
            let text = message.textContent;
            let match = searchRegex.exec(text);
            while (match) {
                numberOfResults++;
                matchRanges.push({offset: match.index, length: match[0].length});
                match = searchRegex.exec(text);
            }

            if (!isEmptyObject(matchRanges))
                this._highlightRanges(message, matchRanges);

            let classList = message.classList;
            if (!isEmptyObject(matchRanges))
                classList.remove(WI.LogContentView.FilteredOutBySearchStyleClassName);
            else
                classList.add(WI.LogContentView.FilteredOutBySearchStyleClassName);
        }, this);

        this.dispatchEventToListeners(WI.ContentView.Event.NumberOfSearchResultsDidChange);

        this._findBanner.numberOfResults = numberOfResults;

        if (!this._selectedSearchMatchIsValid && this._selectedSearchMatch) {
            this._selectedSearchMatch.highlight.classList.remove(WI.LogContentView.SelectedStyleClassName);
            this._selectedSearchMatch = null;
        }
    }

    searchHidden()
    {
        this.searchCleared();
    }

    searchCleared()
    {
        this.performSearch("");
    }

    _highlightRanges(message, matchRanges)
    {
        var highlightedElements = WI.highlightRangesWithStyleClass(message, matchRanges, WI.LogContentView.HighlightedStyleClassName, this._searchHighlightDOMChanges);

        console.assert(highlightedElements.length === matchRanges.length);

        matchRanges.forEach(function(range, index) {
            this._searchMatches.push({message, range, highlight: highlightedElements[index]});

            if (this._selectedSearchMatch && !this._selectedSearchMatchIsValid && this._selectedSearchMatch.message === message) {
                this._selectedSearchMatchIsValid = this._rangesOverlap(this._selectedSearchMatch.range, range);
                if (this._selectedSearchMatchIsValid) {
                    delete this._selectedSearchMatch;
                    this._highlightSearchMatchAtIndex(this._searchMatches.length - 1);
                }
            }
        }, this);
    }

    _rangesOverlap(range1, range2)
    {
        return range1.offset <= range2.offset + range2.length && range2.offset <= range1.offset + range1.length;
    }

    _highlightSearchMatchAtIndex(index)
    {
        if (index >= this._searchMatches.length)
            index = 0;
        else if (index < 0)
            index = this._searchMatches.length - 1;

        if (this._selectedSearchMatch)
            this._selectedSearchMatch.highlight.classList.remove(WI.LogContentView.SelectedStyleClassName);

        this._selectedSearchMatch = this._searchMatches[index];
        this._selectedSearchMatch.highlight.classList.add(WI.LogContentView.SelectedStyleClassName);

        this._selectedSearchMatch.message.scrollIntoViewIfNeeded(false);
    }

    _provisionalLoadStarted()
    {
        this._startedProvisionalLoad = true;
    }

    _reappendProvisionalMessages()
    {
        if (!this._startedProvisionalLoad)
            return;

        this._startedProvisionalLoad = false;

        for (let provisionalMessage of this._provisionalMessages)
            this._logViewController.appendConsoleMessage(provisionalMessage);

        this._provisionalMessages = [];
    }

    _clearProvisionalState()
    {
        this._startedProvisionalLoad = false;
        this._provisionalMessages = [];
    }

    _showHiddenMessagesBannerIfNeeded()
    {
        if (!this._immediatelyHiddenMessages.size) {
            if (this._hiddenMessagesBannerElement)
                this._hiddenMessagesBannerElement.remove();
            return;
        }

        if (!this._hiddenMessagesBannerElement) {
            this._hiddenMessagesBannerElement = document.createElement("div");
            this._hiddenMessagesBannerElement.className = "hidden-messages-banner";

            this._hiddenMessagesBannerElement.appendChild(document.createTextNode(WI.UIString("There are unread messages that have been filtered")));

            let clearFiltersButtonElement = this._hiddenMessagesBannerElement.appendChild(document.createElement("button"));
            clearFiltersButtonElement.textContent = WI.UIString("Clear Filters");
            clearFiltersButtonElement.addEventListener("click", (event) => {
                this._findBanner.clearAndBlur();
                this._scopeBar.resetToDefault();
                console.assert(!this._immediatelyHiddenMessages.size);

                this._hiddenMessagesBannerElement.remove();
            });

            let dismissBannerIconElement = this._hiddenMessagesBannerElement.appendChild(WI.ImageUtilities.useSVGSymbol("Images/Close.svg", "dismiss", WI.UIString("Dismiss")));
            dismissBannerIconElement.addEventListener("click", (event) => {
                this._immediatelyHiddenMessages.clear();
                this._hiddenMessagesBannerElement.remove();
            });
        }

        if (this.element.firstChild !== this._hiddenMessagesBannerElement)
            this.element.insertAdjacentElement("afterbegin", this._hiddenMessagesBannerElement);
    }
};

WI.LogContentView.Scopes = {
    All: "log-all",
    Debugs: "log-debugs",
    Errors: "log-errors",
    Evaluations: "log-evaluations",
    Infos: "log-infos",
    Logs: "log-logs",
    Warnings: "log-warnings",

    AllChannels: "log-all-channels",
    Media: "log-media",
    MediaSource: "log-mediasource",
    WebRTC: "log-webrtc",
};

WI.LogContentView.ItemWrapperStyleClassName = "console-item";
WI.LogContentView.FilteredOutStyleClassName = "filtered-out";
WI.LogContentView.SelectedStyleClassName = "selected";
WI.LogContentView.SearchInProgressStyleClassName = "search-in-progress";
WI.LogContentView.FilteredOutBySearchStyleClassName = "filtered-out-by-search";
WI.LogContentView.HighlightedStyleClassName = "highlighted";
