/*
 * 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.CodeMirrorCompletionController = class CodeMirrorCompletionController extends WI.Object
{
    constructor(codeMirror, delegate, stopCharactersRegex)
    {
        super();

        console.assert(codeMirror);

        this._codeMirror = codeMirror;
        this._stopCharactersRegex = stopCharactersRegex || null;
        this._delegate = delegate || null;

        this._startOffset = NaN;
        this._endOffset = NaN;
        this._lineNumber = NaN;
        this._prefix = "";
        this._noEndingSemicolon = false;
        this._completions = [];
        this._extendedCompletionProviders = {};

        this._suggestionsView = new WI.CompletionSuggestionsView(this);

        this._keyMap = {
            "Up": this._handleUpKey.bind(this),
            "Down": this._handleDownKey.bind(this),
            "Right": this._handleRightOrEnterKey.bind(this),
            "Esc": this._handleEscapeKey.bind(this),
            "Enter": this._handleRightOrEnterKey.bind(this),
            "Tab": this._handleTabKey.bind(this),
            "Cmd-A": this._handleHideKey.bind(this),
            "Cmd-Z": this._handleHideKey.bind(this),
            "Shift-Cmd-Z": this._handleHideKey.bind(this),
            "Cmd-Y": this._handleHideKey.bind(this)
        };

        this._handleChangeListener = this._handleChange.bind(this);
        this._handleCursorActivityListener = this._handleCursorActivity.bind(this);
        this._handleHideActionListener = this._handleHideAction.bind(this);

        this._codeMirror.addKeyMap(this._keyMap);

        this._codeMirror.on("change", this._handleChangeListener);
        this._codeMirror.on("cursorActivity", this._handleCursorActivityListener);
        this._codeMirror.on("blur", this._handleHideActionListener);
        this._codeMirror.on("scroll", this._handleHideActionListener);

        this._updatePromise = null;
    }

    // Public

    get delegate()
    {
        return this._delegate;
    }

    addExtendedCompletionProvider(modeName, provider)
    {
        this._extendedCompletionProviders[modeName] = provider;
    }

    updateCompletions(completions, implicitSuffix)
    {
        if (isNaN(this._startOffset) || isNaN(this._endOffset) || isNaN(this._lineNumber))
            return;

        if (!completions || !completions.length) {
            this.hideCompletions();
            return;
        }

        this._completions = completions;

        if (typeof implicitSuffix === "string")
            this._implicitSuffix = implicitSuffix;

        var from = {line: this._lineNumber, ch: this._startOffset};
        var to = {line: this._lineNumber, ch: this._endOffset};

        var firstCharCoords = this._codeMirror.cursorCoords(from);
        var lastCharCoords = this._codeMirror.cursorCoords(to);
        var bounds = new WI.Rect(firstCharCoords.left, firstCharCoords.top, lastCharCoords.right - firstCharCoords.left, firstCharCoords.bottom - firstCharCoords.top);

        // Try to restore the previous selected index, otherwise just select the first.
        var index = this._currentCompletion ? completions.indexOf(this._currentCompletion) : 0;
        if (index === -1)
            index = 0;

        if (this._forced || completions.length > 1 || completions[index] !== this._prefix) {
            // Update and show the suggestion list.
            this._suggestionsView.update(completions, index);
            this._suggestionsView.show(bounds);
        } else if (this._implicitSuffix) {
            // The prefix and the completion exactly match, but there is an implicit suffix.
            // Just hide the suggestion list and keep the completion hint for the implicit suffix.
            this._suggestionsView.hide();
        } else {
            // The prefix and the completion exactly match, hide the completions. Return early so
            // the completion hint isn't updated.
            this.hideCompletions();
            return;
        }

        this._applyCompletionHint(completions[index]);

        this._resolveUpdatePromise(WI.CodeMirrorCompletionController.UpdatePromise.CompletionsFound);
    }

    isCompletionChange(change)
    {
        return this._ignoreChange || change.origin === WI.CodeMirrorCompletionController.CompletionOrigin || change.origin === WI.CodeMirrorCompletionController.DeleteCompletionOrigin;
    }

    isShowingCompletions()
    {
        return this._suggestionsView.visible || (this._completionHintMarker && this._completionHintMarker.find());
    }

    isHandlingClickEvent()
    {
        return this._suggestionsView.isHandlingClickEvent();
    }

    hideCompletions()
    {
        this._suggestionsView.hide();

        this._removeCompletionHint();

        this._startOffset = NaN;
        this._endOffset = NaN;
        this._lineNumber = NaN;
        this._prefix = "";
        this._completions = [];
        this._implicitSuffix = "";
        this._forced = false;

        delete this._currentCompletion;
        delete this._ignoreNextCursorActivity;

        this._resolveUpdatePromise(WI.CodeMirrorCompletionController.UpdatePromise.NoCompletionsFound);
    }

    close()
    {
        this._codeMirror.removeKeyMap(this._keyMap);

        this._codeMirror.off("change", this._handleChangeListener);
        this._codeMirror.off("cursorActivity", this._handleCursorActivityListener);
        this._codeMirror.off("blur", this._handleHideActionListener);
        this._codeMirror.off("scroll", this._handleHideActionListener);
    }

    completeAtCurrentPositionIfNeeded(force)
    {
        this._resolveUpdatePromise(WI.CodeMirrorCompletionController.UpdatePromise.Canceled);

        var update = this._updatePromise = new WI.WrappedPromise;

        this._completeAtCurrentPosition(force);

        return update.promise;
    }

    // Protected

    completionSuggestionsSelectedCompletion(suggestionsView, completionText)
    {
        this._applyCompletionHint(completionText);
    }

    completionSuggestionsClickedCompletion(suggestionsView, completionText)
    {
        // The clicked suggestion causes the editor to loose focus. Restore it so the user can keep typing.
        this._codeMirror.focus();

        this._applyCompletionHint(completionText);
        this._commitCompletionHint();
    }

    set noEndingSemicolon(noEndingSemicolon)
    {
        this._noEndingSemicolon = noEndingSemicolon;
    }

    // Private

    _resolveUpdatePromise(message)
    {
        if (!this._updatePromise)
            return;

        this._updatePromise.resolve(message);
        this._updatePromise = null;
    }

    get _currentReplacementText()
    {
        return this._currentCompletion + this._implicitSuffix;
    }

    _hasPendingCompletion()
    {
        return !isNaN(this._startOffset) && !isNaN(this._endOffset) && !isNaN(this._lineNumber);
    }

    _notifyCompletionsHiddenSoon()
    {
        function notify()
        {
            if (this._completionHintMarker)
                return;

            if (this._delegate && typeof this._delegate.completionControllerCompletionsHidden === "function")
                this._delegate.completionControllerCompletionsHidden(this);
        }

        if (this._notifyCompletionsHiddenIfNeededTimeout)
            clearTimeout(this._notifyCompletionsHiddenIfNeededTimeout);
        this._notifyCompletionsHiddenIfNeededTimeout = setTimeout(notify.bind(this), WI.CodeMirrorCompletionController.CompletionsHiddenDelay);
    }

    _createCompletionHintMarker(position, text)
    {
        var container = document.createElement("span");
        container.classList.add(WI.CodeMirrorCompletionController.CompletionHintStyleClassName);
        container.textContent = text;

        container.addEventListener("mousedown", (event) => {
            event.preventDefault();
            this._commitCompletionHint();

            // The clicked hint marker causes the editor to loose focus. Restore it so the user can keep typing.
            setTimeout(() => { this._codeMirror.focus(); }, 0);
        });

        this._completionHintMarker = this._codeMirror.setUniqueBookmark(position, {widget: container, insertLeft: true});
    }

    _applyCompletionHint(completionText)
    {
        console.assert(completionText);
        if (!completionText)
            return;

        function update()
        {
            this._currentCompletion = completionText;

            this._removeCompletionHint(true, true);

            var replacementText = this._currentReplacementText;

            var from = {line: this._lineNumber, ch: this._startOffset};
            var cursor = {line: this._lineNumber, ch: this._endOffset};
            var currentText = this._codeMirror.getRange(from, cursor);

            this._createCompletionHintMarker(cursor, replacementText.replace(currentText, ""));
        }

        this._ignoreChange = true;
        this._ignoreNextCursorActivity = true;

        this._codeMirror.operation(update.bind(this));

        delete this._ignoreChange;
    }

    _commitCompletionHint()
    {
        function update()
        {
            this._removeCompletionHint(true, true);

            var replacementText = this._currentReplacementText;

            var from = {line: this._lineNumber, ch: this._startOffset};
            var cursor = {line: this._lineNumber, ch: this._endOffset};
            var to = {line: this._lineNumber, ch: this._startOffset + replacementText.length};

            var lastChar = this._currentCompletion.charAt(this._currentCompletion.length - 1);
            var isClosing = ")]}".indexOf(lastChar);
            if (isClosing !== -1)
                to.ch -= 1 + this._implicitSuffix.length;

            this._codeMirror.replaceRange(replacementText, from, cursor, WI.CodeMirrorCompletionController.CompletionOrigin);

            // Don't call _removeLastChangeFromHistory here to allow the committed completion to be undone.

            this._codeMirror.setCursor(to);

            this.hideCompletions();
        }

        this._ignoreChange = true;
        this._ignoreNextCursorActivity = true;

        this._codeMirror.operation(update.bind(this));

        delete this._ignoreChange;
    }

    _removeLastChangeFromHistory()
    {
        var history = this._codeMirror.getHistory();

        // We don't expect a undone history. But if there is one clear it. If could lead to undefined behavior.
        console.assert(!history.undone.length);
        history.undone = [];

        // Pop the last item from the done history.
        console.assert(history.done.length);
        history.done.pop();

        this._codeMirror.setHistory(history);
    }

    _removeCompletionHint(nonatomic, dontRestorePrefix)
    {
        if (!this._completionHintMarker)
            return;

        this._notifyCompletionsHiddenSoon();

        function clearMarker(marker)
        {
            if (!marker)
                return;

            var range = marker.find();
            if (range)
                marker.clear();

            return null;
        }

        function update()
        {
            this._completionHintMarker = clearMarker(this._completionHintMarker);

            if (dontRestorePrefix)
                return;

            console.assert(!isNaN(this._startOffset));
            console.assert(!isNaN(this._endOffset));
            console.assert(!isNaN(this._lineNumber));

            var from = {line: this._lineNumber, ch: this._startOffset};
            var to = {line: this._lineNumber, ch: this._endOffset};

            this._codeMirror.replaceRange(this._prefix, from, to, WI.CodeMirrorCompletionController.DeleteCompletionOrigin);
            this._removeLastChangeFromHistory();
        }

        if (nonatomic) {
            update.call(this);
            return;
        }

        this._ignoreChange = true;

        this._codeMirror.operation(update.bind(this));

        delete this._ignoreChange;
    }

    _scanStringForExpression(modeName, string, startOffset, direction, allowMiddleAndEmpty, includeStopCharacter, ignoreInitialUnmatchedOpenBracket, stopCharactersRegex)
    {
        console.assert(direction === -1 || direction === 1);

        var stopCharactersRegex = stopCharactersRegex || this._stopCharactersRegex || WI.CodeMirrorCompletionController.DefaultStopCharactersRegexModeMap[modeName] || WI.CodeMirrorCompletionController.GenericStopCharactersRegex;

        function isStopCharacter(character)
        {
            return stopCharactersRegex.test(character);
        }

        function isOpenBracketCharacter(character)
        {
            return WI.CodeMirrorCompletionController.OpenBracketCharactersRegex.test(character);
        }

        function isCloseBracketCharacter(character)
        {
            return WI.CodeMirrorCompletionController.CloseBracketCharactersRegex.test(character);
        }

        function matchingBracketCharacter(character)
        {
            return WI.CodeMirrorCompletionController.MatchingBrackets[character];
        }

        var endOffset = Math.min(startOffset, string.length);

        var endOfLineOrWord = endOffset === string.length || isStopCharacter(string.charAt(endOffset));

        if (!endOfLineOrWord && !allowMiddleAndEmpty)
            return null;

        var bracketStack = [];
        var bracketOffsetStack = [];

        var startOffset = endOffset;
        var firstOffset = endOffset + direction;
        for (var i = firstOffset; direction > 0 ? i < string.length : i >= 0; i += direction) {
            var character = string.charAt(i);

            // Ignore stop characters when we are inside brackets.
            if (isStopCharacter(character) && !bracketStack.length)
                break;

            if (isCloseBracketCharacter(character)) {
                bracketStack.push(character);
                bracketOffsetStack.push(i);
            } else if (isOpenBracketCharacter(character)) {
                if ((!ignoreInitialUnmatchedOpenBracket || i !== firstOffset) && (!bracketStack.length || matchingBracketCharacter(character) !== bracketStack.lastValue))
                    break;

                bracketOffsetStack.pop();
                bracketStack.pop();
            }

            startOffset = i + (direction > 0 ? 1 : 0);
        }

        if (bracketOffsetStack.length)
            startOffset = bracketOffsetStack.pop() + 1;

        if (includeStopCharacter && startOffset > 0 && startOffset < string.length)
            startOffset += direction;

        if (direction > 0) {
            var tempEndOffset = endOffset;
            endOffset = startOffset;
            startOffset = tempEndOffset;
        }

        return {string: string.substring(startOffset, endOffset), startOffset, endOffset};
    }

    _completeAtCurrentPosition(force)
    {
        if (this._codeMirror.somethingSelected()) {
            this.hideCompletions();
            return;
        }

        this._removeCompletionHint(true, true);

        var cursor = this._codeMirror.getCursor();
        var token = this._codeMirror.getTokenAt(cursor);

        // Don't try to complete inside comments or strings.
        if (token.type && /\b(comment|string)\b/.test(token.type)) {
            this.hideCompletions();
            return;
        }

        var mode = this._codeMirror.getMode();
        var innerMode = CodeMirror.innerMode(mode, token.state).mode;
        var modeName = innerMode.alternateName || innerMode.name;

        var lineNumber = cursor.line;
        var lineString = this._codeMirror.getLine(lineNumber);

        var backwardScanResult = this._scanStringForExpression(modeName, lineString, cursor.ch, -1, force);
        if (!backwardScanResult) {
            this.hideCompletions();
            return;
        }

        var forwardScanResult = this._scanStringForExpression(modeName, lineString, cursor.ch, 1, true, true);
        var suffix = forwardScanResult.string;

        this._ignoreNextCursorActivity = true;

        this._startOffset = backwardScanResult.startOffset;
        this._endOffset = backwardScanResult.endOffset;
        this._lineNumber = lineNumber;
        this._prefix = backwardScanResult.string;
        this._completions = [];
        this._implicitSuffix = "";
        this._forced = force;

        var baseExpressionStopCharactersRegex = WI.CodeMirrorCompletionController.BaseExpressionStopCharactersRegexModeMap[modeName];
        if (baseExpressionStopCharactersRegex)
            var baseScanResult = this._scanStringForExpression(modeName, lineString, this._startOffset, -1, true, false, true, baseExpressionStopCharactersRegex);

        if (!force && !backwardScanResult.string && (!baseScanResult || !baseScanResult.string)) {
            this.hideCompletions();
            return;
        }

        var defaultCompletions = [];

        switch (modeName) {
        case "css":
            defaultCompletions = this._generateCSSCompletions(token, baseScanResult ? baseScanResult.string : null, suffix);
            break;
        case "javascript":
            defaultCompletions = this._generateJavaScriptCompletions(token, baseScanResult ? baseScanResult.string : null, suffix);
            break;
        }

        var extendedCompletionsProvider = this._extendedCompletionProviders[modeName];
        if (extendedCompletionsProvider) {
            extendedCompletionsProvider.completionControllerCompletionsNeeded(this, defaultCompletions, baseScanResult ? baseScanResult.string : null, this._prefix, suffix, force);
            return;
        }

        if (this._delegate && typeof this._delegate.completionControllerCompletionsNeeded === "function")
            this._delegate.completionControllerCompletionsNeeded(this, this._prefix, defaultCompletions, baseScanResult ? baseScanResult.string : null, suffix, force);
        else
            this.updateCompletions(defaultCompletions);
    }

    _generateCSSCompletions(mainToken, base, suffix)
    {
        // We support completion inside CSS block context and functions.
        if (mainToken.state.state === "media" || mainToken.state.state === "top")
            return [];

        // Don't complete in the middle of a property name.
        if (/^[a-z]/i.test(suffix))
            return [];

        var token = mainToken;
        var lineNumber = this._lineNumber;

        let getPreviousToken = () => {
            // Found the beginning of the line. Go to the previous line.
            if (!token.start) {
                --lineNumber;

                // No more lines, stop.
                if (lineNumber < 0)
                    return null;
            }

            return this._codeMirror.getTokenAt({line: lineNumber, ch: token.start ? token.start : Number.MAX_VALUE});
        };

        // Inside a function, determine the function name.
        if (token.state.state === "parens") {
            // Scan backwards looking for the function paren boundary.
            while (token && token.state.state === "parens" && token.string !== "(")
                token = getPreviousToken();

            // The immediately preceding token should have the function name.
            if (token)
                token = getPreviousToken();

            // No completions if no function name found.
            if (!token)
                return [];

            let functionName = token.string;
            if (!functionName)
                return [];

            let functionCompletions = WI.CSSKeywordCompletions.forFunction(functionName).startsWith(this._prefix);

            if (this._delegate && this._delegate.completionControllerCSSFunctionValuesNeeded)
                functionCompletions = this._delegate.completionControllerCSSFunctionValuesNeeded(this, functionName, functionCompletions);

            return functionCompletions;
        }

        // Scan backwards looking for the current property.
        while (token.state.state === "prop") {
            let previousToken = getPreviousToken();
            if (!previousToken)
                break;
            token = previousToken;
        }

        // If we have a property token and it's not the main token, then we are working on
        // the value for that property and should complete allowed values.
        if (mainToken !== token && token.type && /\bproperty\b/.test(token.type)) {
            var propertyName = token.string;

            // If there is a suffix and it isn't a semicolon, then we should use a space since
            // the user is editing in the middle. Likewise if the suffix starts with an open
            // paren we are changing a function name so don't add a suffix.
            this._implicitSuffix = " ";
            if (suffix === ";")
                this._implicitSuffix = this._noEndingSemicolon ? "" : ";";
            else if (suffix.startsWith("("))
                this._implicitSuffix = "";

            // Don't use an implicit suffix if it would be the same as the existing suffix.
            if (this._implicitSuffix === suffix)
                this._implicitSuffix = "";

            let completions = WI.CSSKeywordCompletions.forProperty(propertyName).startsWith(this._prefix);

            if (suffix.startsWith("("))
                completions = completions.map((x) => x.replace(/\(\)$/, ""));

            return completions;
        }

        this._implicitSuffix = suffix !== ":" ? ": " : "";

        // Complete property names.
        return WI.CSSCompletions.cssNameCompletions.startsWith(this._prefix);
    }

    _generateJavaScriptCompletions(mainToken, base, suffix)
    {
        // If there is a base expression then we should not attempt to match any keywords or variables.
        // Allow only open bracket characters at the end of the base, otherwise leave completions with
        // a base up to the delegate to figure out.
        if (base && !/[({[]$/.test(base))
            return [];

        var matchingWords = [];

        var prefix = this._prefix;

        var localState = mainToken.state.localState ? mainToken.state.localState : mainToken.state;

        var declaringVariable = localState.lexical.type === "vardef";
        var insideSwitch = localState.lexical.prev ? localState.lexical.prev.info === "switch" : false;
        var insideBlock = localState.lexical.prev ? localState.lexical.prev.type === "}" : false;
        var insideParenthesis = localState.lexical.type === ")";
        var insideBrackets = localState.lexical.type === "]";

        // FIXME: Include module keywords if we know this is a module environment.
        // var moduleKeywords = ["default", "export", "import"];

        const allKeywords = [
            "break", "case", "catch", "class", "const", "continue", "debugger", "default",
            "delete", "do", "else", "extends", "false", "finally", "for", "function",
            "if", "in", "Infinity", "instanceof", "let", "NaN", "new", "null", "of",
            "return", "static", "super", "switch", "this", "throw", "true", "try",
            "typeof", "undefined", "var", "void", "while", "with", "yield"
        ];
        const valueKeywords = ["false", "Infinity", "NaN", "null", "this", "true", "undefined", "globalThis"];

        const allowedKeywordsInsideBlocks = new Set(allKeywords);
        const allowedKeywordsWhenDeclaringVariable = new Set(valueKeywords);
        const allowedKeywordsInsideParenthesis = new Set(valueKeywords.concat(["class", "function"]));
        const allowedKeywordsInsideBrackets = allowedKeywordsInsideParenthesis;
        const allowedKeywordsOnlyInsideSwitch = new Set(["case", "default"]);

        function matchKeywords(keywords)
        {
            for (let keyword of keywords) {
                if (!insideSwitch && allowedKeywordsOnlyInsideSwitch.has(keyword))
                    continue;
                if (insideBlock && !allowedKeywordsInsideBlocks.has(keyword))
                    continue;
                if (insideBrackets && !allowedKeywordsInsideBrackets.has(keyword))
                    continue;
                if (insideParenthesis && !allowedKeywordsInsideParenthesis.has(keyword))
                    continue;
                if (declaringVariable && !allowedKeywordsWhenDeclaringVariable.has(keyword))
                    continue;
                if (!keyword.startsWith(prefix))
                    continue;
                matchingWords.push(keyword);
            }
        }

        function matchVariables()
        {
            function filterVariables(variables)
            {
                for (var variable = variables; variable; variable = variable.next) {
                    // Don't match the variable if this token is in a variable declaration.
                    // Otherwise the currently typed text will always match and that isn't useful.
                    if (declaringVariable && variable.name === prefix)
                        continue;

                    if (variable.name.startsWith(prefix) && !matchingWords.includes(variable.name))
                        matchingWords.push(variable.name);
                }
            }

            var context = localState.context;
            while (context) {
                if (context.vars)
                    filterVariables(context.vars);
                context = context.prev;
            }

            if (localState.localVars)
                filterVariables(localState.localVars);
            if (localState.globalVars)
                filterVariables(localState.globalVars);
        }

        switch (suffix.substring(0, 1)) {
        case "":
        case " ":
            matchVariables();
            matchKeywords(allKeywords);
            break;

        case ".":
        case "[":
            matchVariables();
            matchKeywords(["false", "Infinity", "NaN", "this", "true"]);
            break;

        case "(":
            matchVariables();
            matchKeywords(["catch", "else", "for", "function", "if", "return", "switch", "throw", "while", "with", "yield"]);
            break;

        case "{":
            matchKeywords(["do", "else", "finally", "return", "try", "yield"]);
            break;

        case ":":
            if (insideSwitch)
                matchKeywords(["case", "default"]);
            break;

        case ";":
            matchVariables();
            matchKeywords(valueKeywords);
            matchKeywords(["break", "continue", "debugger", "return", "void"]);
            break;
        }

        return matchingWords;
    }

    _handleUpKey(codeMirror)
    {
        if (!this._hasPendingCompletion())
            return CodeMirror.Pass;

        if (!this.isShowingCompletions())
            return;

        this._suggestionsView.selectPrevious();
    }

    _handleDownKey(codeMirror)
    {
        if (!this._hasPendingCompletion())
            return CodeMirror.Pass;

        if (!this.isShowingCompletions())
            return;

        this._suggestionsView.selectNext();
    }

    _handleRightOrEnterKey(codeMirror)
    {
        if (!this._hasPendingCompletion())
            return CodeMirror.Pass;

        if (!this.isShowingCompletions())
            return;

        this._commitCompletionHint();
    }

    _handleEscapeKey(codeMirror)
    {
        var delegateImplementsShouldAllowEscapeCompletion = this._delegate && typeof this._delegate.completionControllerShouldAllowEscapeCompletion === "function";
        if (this._hasPendingCompletion())
            this.hideCompletions();
        else if (this._codeMirror.getOption("readOnly"))
            return CodeMirror.Pass;
        else if (!delegateImplementsShouldAllowEscapeCompletion || this._delegate.completionControllerShouldAllowEscapeCompletion(this))
            this._completeAtCurrentPosition(true);
        else
            return CodeMirror.Pass;
    }

    _handleTabKey(codeMirror)
    {
        if (!this._hasPendingCompletion())
            return CodeMirror.Pass;

        if (!this.isShowingCompletions())
            return;

        console.assert(this._completions.length);
        if (!this._completions.length)
            return;

        console.assert(this._currentCompletion);
        if (!this._currentCompletion)
            return;

        // Commit the current completion if there is only one suggestion.
        if (this._completions.length === 1) {
            this._commitCompletionHint();
            return;
        }

        var prefixLength = this._prefix.length;

        var commonPrefix = this._completions[0];
        for (var i = 1; i < this._completions.length; ++i) {
            var completion = this._completions[i];
            var lastIndex = Math.min(commonPrefix.length, completion.length);
            for (var j = prefixLength; j < lastIndex; ++j) {
                if (commonPrefix[j] !== completion[j]) {
                    commonPrefix = commonPrefix.substr(0, j);
                    break;
                }
            }
        }

        // Commit the current completion if there is no common prefix that is longer.
        if (commonPrefix === this._prefix) {
            this._commitCompletionHint();
            return;
        }

        // Set the prefix to the common prefix so _applyCompletionHint will insert the
        // common prefix as commited text. Adjust _endOffset to match the new prefix.
        this._prefix = commonPrefix;
        this._endOffset = this._startOffset + commonPrefix.length;

        this._applyCompletionHint(this._currentCompletion);
    }

    _handleChange(codeMirror, change)
    {
        if (this.isCompletionChange(change))
            return;

        this._ignoreNextCursorActivity = true;

        if (!change.origin || change.origin.charAt(0) !== "+") {
            this.hideCompletions();
            return;
        }

        // Only complete on delete if we are showing completions already.
        if (change.origin === "+delete" && !this._hasPendingCompletion())
            return;

        this._completeAtCurrentPosition(false);
    }

    _handleCursorActivity(codeMirror)
    {
        if (this._ignoreChange)
            return;

        if (this._ignoreNextCursorActivity) {
            delete this._ignoreNextCursorActivity;
            return;
        }

        this.hideCompletions();
    }

    _handleHideKey(codeMirror)
    {
        this.hideCompletions();

        return CodeMirror.Pass;
    }

    _handleHideAction(codeMirror)
    {
        // Clicking a suggestion causes the editor to blur. We don't want to hide completions in this case.
        if (this.isHandlingClickEvent())
            return;

        this.hideCompletions();
    }
};

WI.CodeMirrorCompletionController.UpdatePromise = {
    Canceled: "code-mirror-completion-controller-canceled",
    CompletionsFound: "code-mirror-completion-controller-completions-found",
    NoCompletionsFound: "code-mirror-completion-controller-no-completions-found"
};

WI.CodeMirrorCompletionController.GenericStopCharactersRegex = /[\s=:;,]/;
WI.CodeMirrorCompletionController.DefaultStopCharactersRegexModeMap = {"css": /[\s:;,{}()]/, "javascript": /[\s=:;,!+\-*/%&|^~?<>.{}()[\]]/};
WI.CodeMirrorCompletionController.BaseExpressionStopCharactersRegexModeMap = {"javascript": /[\s=:;,!+\-*/%&|^~?<>]/};
WI.CodeMirrorCompletionController.OpenBracketCharactersRegex = /[({[]/;
WI.CodeMirrorCompletionController.CloseBracketCharactersRegex = /[)}\]]/;
WI.CodeMirrorCompletionController.MatchingBrackets = {"{": "}", "(": ")", "[": "]", "}": "{", ")": "(", "]": "["};
WI.CodeMirrorCompletionController.CompletionHintStyleClassName = "completion-hint";
WI.CodeMirrorCompletionController.CompletionsHiddenDelay = 250;
WI.CodeMirrorCompletionController.CompletionTypingDelay = 250;
WI.CodeMirrorCompletionController.CompletionOrigin = "+completion";
WI.CodeMirrorCompletionController.DeleteCompletionOrigin = "+delete-completion";
