/*
 * 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.element, 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.High;
        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.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
        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.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
        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.High;
        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.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.element];
    }

    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 {
            url: WI.FileUtilities.inspectorURLForFilename("Console.txt"),
            content: this._formatMessagesAsData(false),
            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();
    }

    // Protected

    layout()
    {
        this._scrollElementHeight = this.messagesElement.getBoundingClientRect().height;
    }

    // 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({
                    url: WI.FileUtilities.inspectorURLForFilename("Console.txt"),
                    content: this._formatMessagesAsData(true),
                }, 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)
                wrapper = selection.focusNode.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)
            this._ensureMessageIsVisible(this._selectedMessages.lastValue);
    }

    _ensureMessageIsVisible(message)
    {
        if (!message)
            return;

        var y = this._positionForMessage(message).y;
        if (y < 0) {
            this.element.scrollTop += y;
            return;
        }

        var nextMessage = this._nextMessage(message);
        if (nextMessage) {
            y = this._positionForMessage(nextMessage).y;
            if (y > this._scrollElementHeight)
                this.element.scrollTop += y - this._scrollElementHeight;
        } else {
            y += message.getBoundingClientRect().height;
            if (y > this._scrollElementHeight)
                this.element.scrollTop += y - this._scrollElementHeight;
        }
    }

    _positionForMessage(message)
    {
        var pagePoint = window.webkitConvertPointFromNodeToPage(message, new WebKitPoint(0, 0));
        return window.webkitConvertPointFromPageToNode(this.element, pagePoint);
    }

    _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()
    {
        WI.showConsoleTab();
    }

    _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._ensureMessageIsVisible(this._selectedSearchMatch.message);
    }

    _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";
