/*
 * 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.
 */

WI.ConsolePrompt = class ConsolePrompt extends WI.View
{
    constructor(delegate, mimeType)
    {
        super();

        mimeType = parseMIMEType(mimeType).type;

        this.element.classList.add("console-prompt", WI.SyntaxHighlightedStyleClassName);

        this._delegate = delegate || null;

        this._codeMirror = WI.CodeMirrorEditor.create(this.element, {
            lineWrapping: true,
            mode: {name: mimeType, globalVars: true},
            indentWithTabs: true,
            indentUnit: 4,
            matchBrackets: true
        });

        var keyMap = {
            "Up": this._handlePreviousKey.bind(this),
            "Down": this._handleNextKey.bind(this),
            "Ctrl-P": this._handlePreviousKey.bind(this),
            "Ctrl-N": this._handleNextKey.bind(this),
            "Enter": this._handleEnterKey.bind(this),
            "Cmd-Enter": this._handleCommandEnterKey.bind(this),
            "Tab": this._handleTabKey.bind(this),
            "Esc": this._handleEscapeKey.bind(this)
        };

        this._codeMirror.addKeyMap(keyMap);

        this._completionController = new WI.CodeMirrorCompletionController(this._codeMirror, this);
        this._completionController.addExtendedCompletionProvider("javascript", WI.javaScriptRuntimeCompletionProvider);

        this._history = [{}];
        this._historyIndex = 0;
    }

    // Public

    get delegate()
    {
        return this._delegate;
    }

    set delegate(delegate)
    {
        this._delegate = delegate || null;
    }

    set escapeKeyHandlerWhenEmpty(handler)
    {
        this._escapeKeyHandlerWhenEmpty = handler;
    }

    get text()
    {
        return this._codeMirror.getValue();
    }

    set text(text)
    {
        this._codeMirror.setValue(text || "");
        this._codeMirror.clearHistory();
        this._codeMirror.markClean();
    }

    get history()
    {
        this._history[this._historyIndex] = this._historyEntryForCurrentText();
        return this._history;
    }

    set history(history)
    {
        this._history = history instanceof Array ? history.slice(0, WI.ConsolePrompt.MaximumHistorySize) : [{}];
        this._historyIndex = 0;
        this._restoreHistoryEntry(0);
    }

    get focused()
    {
        return this._codeMirror.getWrapperElement().classList.contains("CodeMirror-focused");
    }

    focus()
    {
        this._codeMirror.focus();
    }

    updateCompletions(completions, implicitSuffix)
    {
        this._completionController.updateCompletions(completions, implicitSuffix);
    }

    pushHistoryItem(text)
    {
        this._commitHistoryEntry({text});
    }

    // Protected

    completionControllerCompletionsNeeded(completionController, prefix, defaultCompletions, base, suffix, forced)
    {
        if (this.delegate && typeof this.delegate.consolePromptCompletionsNeeded === "function")
            this.delegate.consolePromptCompletionsNeeded(this, defaultCompletions, base, prefix, suffix, forced);
        else
            this._completionController.updateCompletions(defaultCompletions);
    }

    completionControllerShouldAllowEscapeCompletion(completionController)
    {
        // Only allow escape to complete if there is text in the prompt. Otherwise allow it to pass through
        // so escape to toggle the quick console still works.
        return !!this.text;
    }

    layout()
    {
        if (this.layoutReason === WI.View.LayoutReason.Resize && this.text)
            this._codeMirror.refresh();
    }

    // Private

    _handleTabKey(codeMirror)
    {
        var cursor = codeMirror.getCursor();
        var line = codeMirror.getLine(cursor.line);

        if (!line.trim().length)
            return CodeMirror.Pass;

        var firstNonSpace = line.search(/[^\s]/);

        if (cursor.ch <= firstNonSpace)
            return CodeMirror.Pass;

        this._completionController.completeAtCurrentPositionIfNeeded().then(function(result) {
            if (result === WI.CodeMirrorCompletionController.UpdatePromise.NoCompletionsFound)
                InspectorFrontendHost.beep();
        });
    }

    _handleEscapeKey(codeMirror)
    {
        if (this.text)
            return CodeMirror.Pass;

        if (!this._escapeKeyHandlerWhenEmpty)
            return CodeMirror.Pass;

        this._escapeKeyHandlerWhenEmpty();
    }

    _handlePreviousKey(codeMirror)
    {
        if (this._codeMirror.somethingSelected())
            return CodeMirror.Pass;

        // Pass unless we are on the first line.
        if (this._codeMirror.getCursor().line)
            return CodeMirror.Pass;

        var historyEntry = this._history[this._historyIndex + 1];
        if (!historyEntry)
            return CodeMirror.Pass;

        this._rememberCurrentTextInHistory();

        ++this._historyIndex;

        this._restoreHistoryEntry(this._historyIndex);
    }

    _handleNextKey(codeMirror)
    {
        if (this._codeMirror.somethingSelected())
            return CodeMirror.Pass;

        // Pass unless we are on the last line.
        if (this._codeMirror.getCursor().line !== this._codeMirror.lastLine())
            return CodeMirror.Pass;

        var historyEntry = this._history[this._historyIndex - 1];
        if (!historyEntry)
            return CodeMirror.Pass;

        this._rememberCurrentTextInHistory();

        --this._historyIndex;

        this._restoreHistoryEntry(this._historyIndex);
    }

    _handleEnterKey(codeMirror, forceCommit, keepCurrentText)
    {
        var currentText = this.text;

        // Always do nothing when there is just whitespace.
        if (!currentText.trim())
            return;

        var cursor = this._codeMirror.getCursor();
        var lastLine = this._codeMirror.lastLine();
        var lastLineLength = this._codeMirror.getLine(lastLine).length;
        var cursorIsAtLastPosition = positionsEqual(cursor, {line: lastLine, ch: lastLineLength});

        function positionsEqual(a, b)
        {
            console.assert(a);
            console.assert(b);
            return a.line === b.line && a.ch === b.ch;
        }

        function commitTextOrInsertNewLine(commit)
        {
            if (!commit) {
                // Only insert a new line if the previous cursor and the current cursor are in the same position.
                if (positionsEqual(cursor, this._codeMirror.getCursor()))
                    CodeMirror.commands.newlineAndIndent(this._codeMirror);
                return;
            }

            this._commitHistoryEntry(this._historyEntryForCurrentText());

            if (!keepCurrentText) {
                this._codeMirror.setValue("");
                this._codeMirror.clearHistory();
            }

            if (this.delegate && typeof this.delegate.consolePromptHistoryDidChange === "function")
                this.delegate.consolePromptHistoryDidChange(this);

            if (this.delegate && typeof this.delegate.consolePromptTextCommitted === "function")
                this.delegate.consolePromptTextCommitted(this, currentText);
        }

        if (!forceCommit && this.delegate && typeof this.delegate.consolePromptShouldCommitText === "function") {
            this.delegate.consolePromptShouldCommitText(this, currentText, cursorIsAtLastPosition, commitTextOrInsertNewLine.bind(this));
            return;
        }

        commitTextOrInsertNewLine.call(this, true);
    }

    _commitHistoryEntry(historyEntry)
    {
        // Replace the previous entry if it does not have text or if the text is the same.
        if (this._history[1] && (!this._history[1].text || this._history[1].text === historyEntry.text)) {
            this._history[1] = historyEntry;
            this._history[0] = {};
        } else {
            // Replace the first history entry and push a new empty one.
            this._history[0] = historyEntry;
            this._history.unshift({});

            // Trim the history length if needed.
            if (this._history.length > WI.ConsolePrompt.MaximumHistorySize)
                this._history = this._history.slice(0, WI.ConsolePrompt.MaximumHistorySize);
        }

        this._historyIndex = 0;
    }

    _handleCommandEnterKey(codeMirror)
    {
        this._handleEnterKey(codeMirror, true, true);
    }

    _restoreHistoryEntry(index)
    {
        var historyEntry = this._history[index];

        this._codeMirror.setValue(historyEntry.text || "");

        if (historyEntry.undoHistory)
            this._codeMirror.setHistory(historyEntry.undoHistory);
        else
            this._codeMirror.clearHistory();

        this._codeMirror.setCursor(historyEntry.cursor || {line: 0});
    }

    _historyEntryForCurrentText()
    {
        return {text: this.text, undoHistory: this._codeMirror.getHistory(), cursor: this._codeMirror.getCursor()};
    }

    _rememberCurrentTextInHistory()
    {
        this._history[this._historyIndex] = this._historyEntryForCurrentText();

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

WI.ConsolePrompt.MaximumHistorySize = 30;
