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

WI.QuickConsole = class QuickConsole extends WI.View
{
    constructor(element)
    {
        super(element);

        this._toggleOrFocusKeyboardShortcut = new WI.KeyboardShortcut(null, WI.KeyboardShortcut.Key.Escape, this._toggleOrFocus.bind(this));
        this._toggleOrFocusKeyboardShortcut.implicitlyPreventsDefault = false;
        this._keyboardShortcutDisabled = false;

        this._useExecutionContextOfInspectedNode = this._canUseExecutionContextOfInspectedNode();
        this._restoreSelectedExecutionContextForFrame = null;

        this.element.classList.add("quick-console");
        this.element.addEventListener("mousedown", this._handleMouseDown.bind(this));
        this.element.addEventListener("dragover", this._handleDragOver.bind(this));
        this.element.addEventListener("drop", this._handleDrop.bind(this), true); // Ensure that dropping a DOM node doesn't copy text.

        this.prompt = new WI.ConsolePrompt(null, "text/javascript");
        this.addSubview(this.prompt);

        // FIXME: CodeMirror 4 has a default "Esc" key handler that always prevents default.
        // Our keyboard shortcut above will respect the default prevented and ignore the event
        // and not toggle the console. Install our own Escape key handler that will trigger
        // when the ConsolePrompt is empty, to restore toggling behavior. A better solution
        // would be for CodeMirror's event handler to pass if it doesn't do anything.
        this.prompt.escapeKeyHandlerWhenEmpty = function() { WI.toggleSplitConsole(); };

        const navigationbarElement = null;
        this._navigationBar = new WI.NavigationBar(navigationbarElement, {sizesToFit: true});
        this.addSubview(this._navigationBar);

        this._activeExecutionContextNavigationItemDivider = new WI.DividerNavigationItem;
        this._navigationBar.addNavigationItem(this._activeExecutionContextNavigationItemDivider);

        this._activeExecutionContextNavigationItem = new WI.NavigationItem("active-execution-context");
        WI.addMouseDownContextMenuHandlers(this._activeExecutionContextNavigationItem.element, this._populateActiveExecutionContextNavigationItemContextMenu.bind(this));
        this._navigationBar.addNavigationItem(this._activeExecutionContextNavigationItem);

        this._updateActiveExecutionContextDisplay();

        WI.settings.consoleSavedResultAlias.addEventListener(WI.Setting.Event.Changed, this._handleConsoleSavedResultAliasSettingChanged, this);
        WI.settings.engineeringShowInternalExecutionContexts.addEventListener(WI.Setting.Event.Changed, this._handleEngineeringShowInternalExecutionContextsSettingChanged, this);

        WI.Frame.addEventListener(WI.Frame.Event.PageExecutionContextChanged, this._handleFramePageExecutionContextChanged, this);
        WI.Frame.addEventListener(WI.Frame.Event.ExecutionContextsCleared, this._handleFrameExecutionContextsCleared, this);
        WI.Frame.addEventListener(WI.Frame.Event.ExecutionContextAdded, this._handleFrameExecutionContextAdded, this);

        WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.ActiveCallFrameDidChange, this._handleDebuggerActiveCallFrameDidChange, this);

        WI.runtimeManager.addEventListener(WI.RuntimeManager.Event.ActiveExecutionContextChanged, this._handleActiveExecutionContextChanged, this);

        WI.notifications.addEventListener(WI.Notification.TransitionPageTarget, this._handleTransitionPageTarget, this);

        WI.targetManager.addEventListener(WI.TargetManager.Event.TargetRemoved, this._handleTargetRemoved, this);

        WI.domManager.addEventListener(WI.DOMManager.Event.InspectedNodeChanged, this._handleInspectedNodeChanged, this);

        WI.consoleDrawer.toggleButtonShortcutTooltip(this._toggleOrFocusKeyboardShortcut);
        WI.consoleDrawer.addEventListener(WI.ConsoleDrawer.Event.CollapsedStateChanged, this._updateStyles, this);
        WI.TabBrowser.addEventListener(WI.TabBrowser.Event.SelectedTabContentViewDidChange, this._updateStyles, this);

        WI.whenTargetsAvailable().then(() => {
            this._updateActiveExecutionContextDisplay();
        });
    }

    // Public

    set keyboardShortcutDisabled(disabled)
    {
        this._keyboardShortcutDisabled = disabled;
    }

    closed()
    {
        WI.settings.consoleSavedResultAlias.removeEventListener(WI.Setting.Event.Changed, this._handleConsoleSavedResultAliasSettingChanged, this);
        WI.settings.engineeringShowInternalExecutionContexts.removeEventListener(WI.Setting.Event.Changed, this._handleEngineeringShowInternalExecutionContextsSettingChanged, this);

        WI.Frame.removeEventListener(WI.Frame.Event.PageExecutionContextChanged, this._handleFramePageExecutionContextChanged, this);
        WI.Frame.removeEventListener(WI.Frame.Event.ExecutionContextsCleared, this._handleFrameExecutionContextsCleared, this);

        WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.ActiveCallFrameDidChange, this._handleDebuggerActiveCallFrameDidChange, this);

        WI.runtimeManager.removeEventListener(WI.RuntimeManager.Event.ActiveExecutionContextChanged, this._handleActiveExecutionContextChanged, this);

        WI.notifications.removeEventListener(WI.Notification.TransitionPageTarget, this._handleTransitionPageTarget, this);

        WI.targetManager.removeEventListener(WI.TargetManager.Event.TargetRemoved, this._handleTargetRemoved, this);

        WI.domManager.removeEventListener(WI.DOMManager.Event.InspectedNodeChanged, this._handleInspectedNodeChanged, this);

        WI.consoleDrawer.removeEventListener(WI.ConsoleDrawer.Event.CollapsedStateChanged, this._updateStyles, this);
        WI.TabBrowser.removeEventListener(WI.TabBrowser.Event.SelectedTabContentViewDidChange, this._updateStyles, this);

        super.closed();
    }

    // Private

    _displayNameForExecutionContext(context, maxLength = Infinity)
    {
        function truncate(string, length) {
            if (!Number.isFinite(maxLength))
                return string;
            return string.trim().truncateMiddle(length);
        }

        if (context.type === WI.ExecutionContext.Type.Internal)
            return WI.unlocalizedString("[Internal] ") + context.name;

        if (context.type === WI.ExecutionContext.Type.User) {
            let extensionName = WI.browserManager.extensionNameForExecutionContext(context);
            if (extensionName)
                return truncate(extensionName, maxLength);
        }

        let target = context.target;
        if (target.type === WI.TargetType.Worker)
            return truncate(target.displayName, maxLength);

        let frame = context.frame;
        if (frame) {
            if (context === frame.executionContextList.pageExecutionContext) {
                let resourceName = frame.mainResource.displayName;
                let frameName = frame.name;
                if (frameName) {
                    // Attempt to show all of the frame name, but ensure that at least 20 characters
                    // of the resource name are shown as well.
                    let frameNameMaxLength = Math.max(maxLength - resourceName.length, 20);
                    return WI.UIString("%s (%s)").format(truncate(frameName, frameNameMaxLength), truncate(resourceName, maxLength - frameNameMaxLength));
                }
                return truncate(resourceName, maxLength);
            }
        }

        return truncate(context.name, maxLength);
    }

    _resolveDesiredActiveExecutionContext(forceInspectedNode)
    {
        let executionContext = null;

        if (this._useExecutionContextOfInspectedNode || forceInspectedNode) {
            let inspectedNode = WI.domManager.inspectedNode;
            if (inspectedNode) {
                let frame = inspectedNode.frame;
                if (frame) {
                    let pageExecutionContext = frame.pageExecutionContext;
                    if (pageExecutionContext)
                        executionContext = pageExecutionContext;
                }
            }
        }

        if (!executionContext && WI.networkManager.mainFrame)
            executionContext = WI.networkManager.mainFrame.pageExecutionContext;

        return executionContext || WI.mainTarget.executionContext;
    }

    _setActiveExecutionContext(context)
    {
        let wasActive = WI.runtimeManager.activeExecutionContext === context;

        WI.runtimeManager.activeExecutionContext = context;

        if (wasActive)
            this._updateActiveExecutionContextDisplay();
    }

    _updateActiveExecutionContextDisplay()
    {
        let toggleHidden = (hidden) => {
            this._activeExecutionContextNavigationItemDivider.hidden = hidden;
            this._activeExecutionContextNavigationItem.hidden = hidden;
        };

        if (WI.debuggerManager.activeCallFrame) {
            toggleHidden(true);
            return;
        }

        if (!WI.runtimeManager.activeExecutionContext || !WI.networkManager.mainFrame) {
            toggleHidden(true);
            return;
        }

        if (WI.networkManager.frames.length === 1 && !WI.targetManager.workerTargets.length) {
            let mainFrameContexts = WI.networkManager.mainFrame.executionContextList.contexts;
            let contextsToShow = mainFrameContexts.filter((context) => context.type !== WI.ExecutionContext.Type.Internal || WI.settings.engineeringShowInternalExecutionContexts.value);
            if (contextsToShow.length <= 1) {
                toggleHidden(true);
                return;
            }
        }

        const maxLength = 40;

        if (this._useExecutionContextOfInspectedNode) {
            this._activeExecutionContextNavigationItem.element.classList.add("automatic");
            this._activeExecutionContextNavigationItem.element.textContent = WI.UIString("Auto \u2014 %s").format(this._displayNameForExecutionContext(WI.runtimeManager.activeExecutionContext, maxLength));
            this._activeExecutionContextNavigationItem.tooltip = WI.UIString("Execution context for %s").format(WI.RuntimeManager.preferredSavedResultPrefix() + "0");
        } else {
            this._activeExecutionContextNavigationItem.element.classList.remove("automatic");
            this._activeExecutionContextNavigationItem.element.textContent = this._displayNameForExecutionContext(WI.runtimeManager.activeExecutionContext, maxLength);
            this._activeExecutionContextNavigationItem.tooltip = this._displayNameForExecutionContext(WI.runtimeManager.activeExecutionContext);
        }

        this._activeExecutionContextNavigationItem.element.appendChild(WI.ImageUtilities.useSVGSymbol("Images/UpDownArrows.svg", "selector-arrows"));

        toggleHidden(false);
    }

    _populateActiveExecutionContextNavigationItemContextMenu(contextMenu)
    {
        const maxLength = 120;

        let activeExecutionContext = WI.runtimeManager.activeExecutionContext;

        if (this._canUseExecutionContextOfInspectedNode()) {
            let executionContextForInspectedNode = this._resolveDesiredActiveExecutionContext(true);
            contextMenu.appendCheckboxItem(WI.UIString("Auto \u2014 %s").format(this._displayNameForExecutionContext(executionContextForInspectedNode, maxLength)), () => {
                this._useExecutionContextOfInspectedNode = true;
                this._setActiveExecutionContext(executionContextForInspectedNode);
            }, this._useExecutionContextOfInspectedNode);

            contextMenu.appendSeparator();
        }

        let indent = 0;
        let addExecutionContext = (context) => {
            if (context.type === WI.ExecutionContext.Type.Internal && !WI.settings.engineeringShowInternalExecutionContexts.value)
                return;

            let additionalIndent = (context.frame && context !== context.frame.executionContextList.pageExecutionContext) || context.type !== WI.ExecutionContext.Type.Normal;

            // Mimic macOS `-[NSMenuItem setIndentationLevel]`.
            contextMenu.appendCheckboxItem("   ".repeat(indent + additionalIndent) + this._displayNameForExecutionContext(context, maxLength), () => {
                this._useExecutionContextOfInspectedNode = false;
                this._setActiveExecutionContext(context);
            }, activeExecutionContext === context);
        };

        let addExecutionContextsForFrame = (frame) => {
            let pageExecutionContext = frame.executionContextList.pageExecutionContext;

            let contexts = frame.executionContextList.contexts.sort((a, b) => {
                if (a === pageExecutionContext)
                    return -1;
                if (b === pageExecutionContext)
                    return 1;

                const executionContextTypeRanking = [
                    WI.ExecutionContext.Type.Normal,
                    WI.ExecutionContext.Type.User,
                    WI.ExecutionContext.Type.Internal,
                ];
                return executionContextTypeRanking.indexOf(a.type) - executionContextTypeRanking.indexOf(b.type);
            });
            for (let context of contexts)
                addExecutionContext(context);
        };

        let mainFrame = WI.networkManager.mainFrame;
        addExecutionContextsForFrame(mainFrame);

        indent = 1;

        let otherFrames = WI.networkManager.frames.filter((frame) => frame !== mainFrame && frame.executionContextList.pageExecutionContext);
        if (otherFrames.length) {
            contextMenu.appendHeader(WI.UIString("Frames", "Frames @ Execution Context Picker", "Title for list of HTML subframe JavaScript execution contexts"));

            for (let frame of otherFrames)
                addExecutionContextsForFrame(frame);
        }

        let workerTargets = WI.targetManager.workerTargets;
        if (workerTargets.length) {
            contextMenu.appendHeader(WI.UIString("Workers", "Workers @ Execution Context Picker", "Title for list of JavaScript web worker execution contexts"));

            for (let target of workerTargets)
                addExecutionContext(target.executionContext);
        }
    }

    _handleMouseDown(event)
    {
        if (event.target !== this.element)
            return;

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

    _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();
            });
        }
    }

    _handleConsoleSavedResultAliasSettingChanged()
    {
        this._updateActiveExecutionContextDisplay();
    }

    _handleEngineeringShowInternalExecutionContextsSettingChanged(event)
    {
        this._updateActiveExecutionContextDisplay();

        if (WI.runtimeManager.activeExecutionContext.type !== WI.ExecutionContext.Type.Internal)
            return;

        this._useExecutionContextOfInspectedNode = this._canUseExecutionContextOfInspectedNode();
        this._setActiveExecutionContext(this._resolveDesiredActiveExecutionContext());
    }

    _handleFramePageExecutionContextChanged(event)
    {
        let frame = event.target;

        if (this._restoreSelectedExecutionContextForFrame !== frame)
            return;

        this._restoreSelectedExecutionContextForFrame = null;

        this._useExecutionContextOfInspectedNode = false;
        this._setActiveExecutionContext(frame.pageExecutionContext);
    }

    _handleFrameExecutionContextAdded(event)
    {
        this._updateActiveExecutionContextDisplay();
    }

    _handleFrameExecutionContextsCleared(event)
    {
        let {committingProvisionalLoad, contexts} = event.data;

        let hasActiveExecutionContext = contexts.some((context) => context === WI.runtimeManager.activeExecutionContext);
        if (!hasActiveExecutionContext) {
            this._updateActiveExecutionContextDisplay();
            return;
        }

        // If this frame is navigating and it is selected in the UI we want to reselect its new item after navigation,
        // however when `_useExecutionContextOfInspectedNode` is true, we should keep the execution context set to `Auto`.
        if (committingProvisionalLoad && !this._restoreSelectedExecutionContextForFrame && !this._useExecutionContextOfInspectedNode) {
            this._restoreSelectedExecutionContextForFrame = event.target;

            // As a fail safe, if the frame never gets an execution context, clear the restore value.
            setTimeout(() => {
                if (!this._restoreSelectedExecutionContextForFrame)
                    return;
                this._restoreSelectedExecutionContextForFrame = null;

                this._useExecutionContextOfInspectedNode = this._canUseExecutionContextOfInspectedNode();
                this._setActiveExecutionContext(this._resolveDesiredActiveExecutionContext());
            }, 100);
            return;
        }

        this._useExecutionContextOfInspectedNode = this._canUseExecutionContextOfInspectedNode();
        this._setActiveExecutionContext(this._resolveDesiredActiveExecutionContext());
    }

    _handleDebuggerActiveCallFrameDidChange(event)
    {
        this._updateActiveExecutionContextDisplay();
    }

    _handleActiveExecutionContextChanged(event)
    {
        this._updateActiveExecutionContextDisplay();
    }

    _handleTransitionPageTarget()
    {
        this._updateActiveExecutionContextDisplay();
    }

    _handleTargetRemoved(event)
    {
        let {target} = event.data;
        if (target !== WI.runtimeManager.activeExecutionContext) {
            this._updateActiveExecutionContextDisplay();
            return;
        }

        this._useExecutionContextOfInspectedNode = this._canUseExecutionContextOfInspectedNode();
        this._setActiveExecutionContext(this._resolveDesiredActiveExecutionContext());
    }

    _handleInspectedNodeChanged(event)
    {
        if (!this._useExecutionContextOfInspectedNode)
            return;

        this._setActiveExecutionContext(this._resolveDesiredActiveExecutionContext());
    }

    _canUseExecutionContextOfInspectedNode()
    {
        return InspectorBackend.hasDomain("DOM");
    }

    _toggleOrFocus(event)
    {
        if (this._keyboardShortcutDisabled)
            return;

        if (this.prompt.focused) {
            WI.toggleSplitConsole();
            event.preventDefault();
        } else if (!WI.isEditingAnyField() && !WI.isEventTargetAnEditableField(event)) {
            this.prompt.focus();
            event.preventDefault();
        }
    }

    _updateStyles()
    {
        this.element.classList.toggle("showing-log", WI.isShowingConsoleTab() || WI.isShowingSplitConsole());
    }
};
