/*
 * 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 = InspectorBackend.hasDomain("DOM");
        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.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(null, null, this);
        WI.Frame.removeEventListener(null, null, this);
        WI.debuggerManager.removeEventListener(null, null, this);
        WI.runtimeManager.removeEventListener(null, null, this);
        WI.targetManager.removeEventListener(null, null, this);
        WI.consoleDrawer.removeEventListener(null, null, this);
        WI.TabBrowser.removeEventListener(null, null, 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 (InspectorBackend.hasDomain("DOM")) {
            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 = InspectorBackend.hasDomain("DOM");
        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);
    }

    _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.
        if (committingProvisionalLoad && !this._restoreSelectedExecutionContextForFrame) {
            this._restoreSelectedExecutionContextForFrame = event.target;

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

        this._useExecutionContextOfInspectedNode = InspectorBackend.hasDomain("DOM");
        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 = InspectorBackend.hasDomain("DOM");
        this._setActiveExecutionContext(this._resolveDesiredActiveExecutionContext());
    }

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

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

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