/*
 * Copyright (C) 2013 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.JavaScriptLogViewController = class JavaScriptLogViewController extends WI.Object
{
    constructor(element, scrollElement, textPrompt, delegate, historySettingIdentifier)
    {
        super();

        console.assert(textPrompt instanceof WI.ConsolePrompt);
        console.assert(historySettingIdentifier);

        this._element = element;
        this._scrollElement = scrollElement;

        this._promptHistorySetting = new WI.Setting(historySettingIdentifier, null);

        this._prompt = textPrompt;
        this._prompt.delegate = this;
        this._prompt.history = this._promptHistorySetting.value;

        this.delegate = delegate;

        this._cleared = true;
        this._previousMessageView = null;
        this._lastCommitted = "";
        this._repeatCountWasInterrupted = false;

        this._sessions = [];
        this._currentSessionOrGroup = null;

        this.messagesAlternateClearKeyboardShortcut = new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.Control, "L", this.requestClearMessages.bind(this), this._element);

        this._messagesFindNextKeyboardShortcut = new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.CommandOrControl, "G", this._handleFindNextShortcut.bind(this), this._element);
        this._messagesFindPreviousKeyboardShortcut = new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.CommandOrControl | WI.KeyboardShortcut.Modifier.Shift, "G", this._handleFindPreviousShortcut.bind(this), this._element);

        this._promptAlternateClearKeyboardShortcut = new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.Control, "L", this.requestClearMessages.bind(this), this._prompt.element);
        this._promptFindNextKeyboardShortcut = new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.CommandOrControl, "G", this._handleFindNextShortcut.bind(this), this._prompt.element);
        this._promptFindPreviousKeyboardShortcut = new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.CommandOrControl | WI.KeyboardShortcut.Modifier.Shift, "G", this._handleFindPreviousShortcut.bind(this), this._prompt.element);

        this._pendingMessagesForSessionOrGroup = new Map;
        this._scheduledRenderIdentifier = 0;

        this.startNewSession();
    }

    // Public

    clear()
    {
        this._cleared = true;

        const clearPreviousSessions = true;
        this.startNewSession(clearPreviousSessions, {newSessionReason: WI.ConsoleSession.NewSessionReason.ConsoleCleared});
    }

    startNewSession(clearPreviousSessions = false, data = {})
    {
        if (clearPreviousSessions) {
            this._pendingMessagesForSessionOrGroup.clear();

            if (this._sessions.length) {
                for (let session of this._sessions)
                    session.element.remove();

                this._sessions = [];
                this._currentSessionOrGroup = null;
            }
        }

        // First session shows the time when the console was opened.
        if (!this._sessions.length)
            data.timestamp = Date.now();

        let lastSession = this._sessions.lastValue;

        // Remove empty session.
        if (lastSession && !lastSession.hasMessages() && !this._pendingMessagesForSessionOrGroup.has(lastSession)) {
            this._sessions.pop();
            lastSession.element.remove();
        }

        let consoleSession = new WI.ConsoleSession(data);

        this._previousMessageView = null;
        this._lastCommitted = "";
        this._repeatCountWasInterrupted = false;

        this._sessions.push(consoleSession);
        this._currentSessionOrGroup = consoleSession;

        this._element.appendChild(consoleSession.element);

        // Make sure the new session is visible.
        consoleSession.element.scrollIntoView();
    }

    appendImmediateExecutionWithResult(text, result, addSpecialUserLogClass, shouldRevealConsole)
    {
        console.assert(result instanceof WI.RemoteObject);

        var commandMessageView = new WI.ConsoleCommandView(text, addSpecialUserLogClass ? "special-user-log" : null);
        this._appendConsoleMessageView(commandMessageView, true);

        function saveResultCallback(savedResultIndex)
        {
            let commandResultMessage = new WI.ConsoleCommandResultMessage(result.target, result, false, savedResultIndex, shouldRevealConsole);
            let commandResultMessageView = new WI.ConsoleMessageView(commandResultMessage);
            this._appendConsoleMessageView(commandResultMessageView, true);
        }

        WI.runtimeManager.saveResult(result, saveResultCallback.bind(this));
    }

    appendConsoleMessage(consoleMessage)
    {
        var consoleMessageView = new WI.ConsoleMessageView(consoleMessage);
        this._appendConsoleMessageView(consoleMessageView);
        return consoleMessageView;
    }

    updatePreviousMessageRepeatCount(count)
    {
        console.assert(this._previousMessageView);
        if (!this._previousMessageView)
            return false;

        var previousIgnoredCount = this._previousMessageView[WI.JavaScriptLogViewController.IgnoredRepeatCount] || 0;
        var previousVisibleCount = this._previousMessageView.repeatCount;

        if (!this._repeatCountWasInterrupted) {
            this._previousMessageView.repeatCount = count - previousIgnoredCount;
            return true;
        }

        var consoleMessage = this._previousMessageView.message;
        var duplicatedConsoleMessageView = new WI.ConsoleMessageView(consoleMessage);
        duplicatedConsoleMessageView[WI.JavaScriptLogViewController.IgnoredRepeatCount] = previousIgnoredCount + previousVisibleCount;
        duplicatedConsoleMessageView.repeatCount = 1;
        this._appendConsoleMessageView(duplicatedConsoleMessageView);

        return true;
    }

    isScrolledToBottom()
    {
        // Lie about being scrolled to the bottom if we have a pending request to scroll to the bottom soon.
        return this._scrollToBottomTimeout || this._scrollElement.isScrolledToBottom();
    }

    scrollToBottom()
    {
        if (this._scrollToBottomTimeout)
            return;

        function delayedWork()
        {
            this._scrollToBottomTimeout = null;
            this._scrollElement.scrollTop = this._scrollElement.scrollHeight;
        }

        // Don't scroll immediately so we are not causing excessive layouts when there
        // are many messages being added at once.
        this._scrollToBottomTimeout = setTimeout(delayedWork.bind(this), 0);
    }

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

    // Protected

    consolePromptHistoryDidChange(prompt)
    {
        this._promptHistorySetting.value = this._prompt.history;
    }

    consolePromptShouldCommitText(prompt, text, cursorIsAtLastPosition, handler)
    {
        // Always commit the text if we are not at the last position.
        if (!cursorIsAtLastPosition) {
            handler(true);
            return;
        }

        function parseFinished(error, result, message, range)
        {
            handler(result !== InspectorBackend.Enum.Runtime.SyntaxErrorType.Recoverable);
        }

        WI.runtimeManager.activeExecutionContext.target.RuntimeAgent.parse(text, parseFinished.bind(this));
    }

    consolePromptTextCommitted(prompt, text)
    {
        console.assert(text);

        if (this._lastCommitted !== text) {
            let commandMessageView = new WI.ConsoleCommandView(text);
            this._appendConsoleMessageView(commandMessageView, true);
            this._lastCommitted = text;
        }

        function printResult(result, wasThrown, savedResultIndex)
        {
            if (!result || this._cleared)
                return;

            let shouldRevealConsole = true;
            let commandResultMessage = new WI.ConsoleCommandResultMessage(result.target, result, wasThrown, savedResultIndex, shouldRevealConsole);
            let commandResultMessageView = new WI.ConsoleMessageView(commandResultMessage);
            this._appendConsoleMessageView(commandResultMessageView, true);
        }

        let options = {
            objectGroup: WI.RuntimeManager.ConsoleObjectGroup,
            includeCommandLineAPI: true,
            doNotPauseOnExceptionsAndMuteConsole: false,
            returnByValue: false,
            generatePreview: true,
            saveResult: true,
            emulateUserGesture: WI.settings.emulateInUserGesture.value,
            sourceURLAppender: appendWebInspectorConsoleEvaluationSourceURL,
        };

        WI.runtimeManager.evaluateInInspectedWindow(text, options, printResult.bind(this));
    }

    // Private

    _handleFindNextShortcut()
    {
        this.delegate.highlightNextSearchMatch();
    }

    _handleFindPreviousShortcut()
    {
        this.delegate.highlightPreviousSearchMatch();
    }

    _appendConsoleMessageView(messageView, repeatCountWasInterrupted)
    {
        let pendingMessagesForSession = this._pendingMessagesForSessionOrGroup.get(this._currentSessionOrGroup);
        if (!pendingMessagesForSession) {
            pendingMessagesForSession = [];
            this._pendingMessagesForSessionOrGroup.set(this._currentSessionOrGroup, pendingMessagesForSession);
        }
        pendingMessagesForSession.push(messageView);

        this._cleared = false;
        this._repeatCountWasInterrupted = repeatCountWasInterrupted || false;

        if (!repeatCountWasInterrupted)
            this._previousMessageView = messageView;

        if (messageView.message && messageView.message.source !== WI.ConsoleMessage.MessageSource.JS)
            this._lastCommitted = "";

        if (WI.consoleContentView.visible)
            this.renderPendingMessagesSoon();

        if (!WI.isShowingConsoleTab() && messageView.message && messageView.message.shouldRevealConsole)
            WI.showSplitConsole();
    }

    renderPendingMessages()
    {
        if (this._scheduledRenderIdentifier) {
            cancelAnimationFrame(this._scheduledRenderIdentifier);
            this._scheduledRenderIdentifier = 0;
        }

        if (!this._pendingMessagesForSessionOrGroup.size)
            return;

        let wasScrolledToBottom = this.isScrolledToBottom();
        let savedCurrentConsoleGroup = this._currentSessionOrGroup;
        let lastMessageView = null;

        const maxMessagesPerFrame = 100;
        let renderedMessages = 0;
        for (let [session, messages] of this._pendingMessagesForSessionOrGroup) {
            this._currentSessionOrGroup = session;

            let messagesToRender = messages.splice(0, maxMessagesPerFrame - renderedMessages);
            for (let message of messagesToRender) {
                message.render();
                this._didRenderConsoleMessageView(message);
            }

            lastMessageView = messagesToRender.lastValue;

            if (!messages.length)
                this._pendingMessagesForSessionOrGroup.delete(session);

            renderedMessages += messagesToRender.length;
            if (renderedMessages >= maxMessagesPerFrame)
                break;
        }

        this._currentSessionOrGroup = savedCurrentConsoleGroup;

        if (wasScrolledToBottom || lastMessageView instanceof WI.ConsoleCommandView || lastMessageView.message.type === WI.ConsoleMessage.MessageType.Result || lastMessageView.message.type === WI.ConsoleMessage.MessageType.Image)
            this.scrollToBottom();

        WI.quickConsole.needsLayout();

        if (this._pendingMessagesForSessionOrGroup.size)
            this.renderPendingMessagesSoon();
    }

    renderPendingMessagesSoon()
    {
        if (this._scheduledRenderIdentifier)
            return;

        this._scheduledRenderIdentifier = requestAnimationFrame(() => this.renderPendingMessages());
    }

    _didRenderConsoleMessageView(messageView)
    {
        var type = messageView instanceof WI.ConsoleCommandView ? null : messageView.message.type;
        if (type === WI.ConsoleMessage.MessageType.EndGroup) {
            var parentGroup = this._currentSessionOrGroup.parentGroup;
            if (parentGroup)
                this._currentSessionOrGroup = parentGroup;
        } else {
            if (type === WI.ConsoleMessage.MessageType.StartGroup || type === WI.ConsoleMessage.MessageType.StartGroupCollapsed) {
                var group = new WI.ConsoleGroup(this._currentSessionOrGroup);
                var groupElement = group.render(messageView);
                this._currentSessionOrGroup.append(groupElement);
                this._currentSessionOrGroup = group;
            } else
                this._currentSessionOrGroup.addMessageView(messageView);
        }

        if (this.delegate && typeof this.delegate.didAppendConsoleMessageView === "function")
            this.delegate.didAppendConsoleMessageView(messageView);
    }
};

WI.JavaScriptLogViewController.CachedPropertiesDuration = 30_000;
WI.JavaScriptLogViewController.IgnoredRepeatCount = Symbol("ignored-repeat-count");
