// Copyright (c) 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
 * @unrestricted
 */
SourceFrame.SourcesTextEditor = class extends TextEditor.CodeMirrorTextEditor {
  /**
   * @param {!SourceFrame.SourcesTextEditorDelegate} delegate
   */
  constructor(delegate) {
    super({
      lineNumbers: true,
      lineWrapping: false,
      bracketMatchingSetting: Common.moduleSetting('textEditorBracketMatching'),
      padBottom: true
    });

    this.codeMirror().addKeyMap({'Enter': 'smartNewlineAndIndent', 'Esc': 'sourcesDismiss'});

    this._delegate = delegate;

    this.codeMirror().on('cursorActivity', this._cursorActivity.bind(this));
    this.codeMirror().on('gutterClick', this._gutterClick.bind(this));
    this.codeMirror().on('scroll', this._scroll.bind(this));
    this.codeMirror().on('focus', this._focus.bind(this));
    this.codeMirror().on('blur', this._blur.bind(this));
    this.codeMirror().on('beforeSelectionChange', this._fireBeforeSelectionChanged.bind(this));
    this.element.addEventListener('contextmenu', this._contextMenu.bind(this), false);

    this.codeMirror().addKeyMap(SourceFrame.SourcesTextEditor._BlockIndentController);
    this._tokenHighlighter = new SourceFrame.SourcesTextEditor.TokenHighlighter(this, this.codeMirror());

    /** @type {!Array<string>} */
    this._gutters = ['CodeMirror-linenumbers'];
    this.codeMirror().setOption('gutters', this._gutters.slice());

    this.codeMirror().setOption('electricChars', false);
    this.codeMirror().setOption('smartIndent', false);

    /**
     * @this {SourceFrame.SourcesTextEditor}
     */
    function updateAnticipateJumpFlag(value) {
      this._isHandlingMouseDownEvent = value;
    }

    this.element.addEventListener('mousedown', updateAnticipateJumpFlag.bind(this, true), true);
    this.element.addEventListener('mousedown', updateAnticipateJumpFlag.bind(this, false), false);
    Common.moduleSetting('textEditorIndent').addChangeListener(this._onUpdateEditorIndentation, this);
    Common.moduleSetting('textEditorAutoDetectIndent').addChangeListener(this._onUpdateEditorIndentation, this);
    Common.moduleSetting('showWhitespacesInEditor').addChangeListener(this._updateWhitespace, this);

    /** @type {?UI.AutocompleteConfig} */
    this._autocompleteConfig = {isWordChar: TextUtils.TextUtils.isWordChar};
    Common.moduleSetting('textEditorAutocompletion').addChangeListener(this._updateAutocomplete, this);
    this._updateAutocomplete();

    this._onUpdateEditorIndentation();
    this._setupWhitespaceHighlight();
  }

  /**
   * @param {!UI.Infobar} infobar
   */
  attachInfobar(infobar) {
    this.element.insertBefore(infobar.element, this.element.firstChild);
    infobar.setParentView(this);
    this.doResize();
  }

  /**
   * @param {!Array.<string>} lines
   * @return {string}
   */
  static _guessIndentationLevel(lines) {
    const tabRegex = /^\t+/;
    let tabLines = 0;
    const indents = {};
    for (let lineNumber = 0; lineNumber < lines.length; ++lineNumber) {
      const text = lines[lineNumber];
      if (text.length === 0 || !TextUtils.TextUtils.isSpaceChar(text[0]))
        continue;
      if (tabRegex.test(text)) {
        ++tabLines;
        continue;
      }
      let i = 0;
      while (i < text.length && TextUtils.TextUtils.isSpaceChar(text[i]))
        ++i;
      if (i % 2 !== 0)
        continue;
      indents[i] = 1 + (indents[i] || 0);
    }
    const linesCountPerIndentThreshold = 3 * lines.length / 100;
    if (tabLines && tabLines > linesCountPerIndentThreshold)
      return '\t';
    let minimumIndent = Infinity;
    for (const i in indents) {
      if (indents[i] < linesCountPerIndentThreshold)
        continue;
      const indent = parseInt(i, 10);
      if (minimumIndent > indent)
        minimumIndent = indent;
    }
    if (minimumIndent === Infinity)
      return Common.moduleSetting('textEditorIndent').get();
    return ' '.repeat(minimumIndent);
  }

  /**
   * @return {boolean}
   */
  _isSearchActive() {
    return !!this._tokenHighlighter.highlightedRegex();
  }

  /**
   * @override
   * @param {number} lineNumber
   */
  scrollToLine(lineNumber) {
    super.scrollToLine(lineNumber);
    this._scroll();
  }

  /**
   * @param {!RegExp} regex
   * @param {?TextUtils.TextRange} range
   */
  highlightSearchResults(regex, range) {
    /**
     * @this {TextEditor.CodeMirrorTextEditor}
     */
    function innerHighlightRegex() {
      if (range) {
        this.scrollLineIntoView(range.startLine);
        if (range.endColumn > TextEditor.CodeMirrorTextEditor.maxHighlightLength)
          this.setSelection(range);
        else
          this.setSelection(TextUtils.TextRange.createFromLocation(range.startLine, range.startColumn));
      }
      this._tokenHighlighter.highlightSearchResults(regex, range);
    }

    if (!this._selectionBeforeSearch)
      this._selectionBeforeSearch = this.selection();

    this.codeMirror().operation(innerHighlightRegex.bind(this));
  }

  cancelSearchResultsHighlight() {
    this.codeMirror().operation(this._tokenHighlighter.highlightSelectedTokens.bind(this._tokenHighlighter));

    if (this._selectionBeforeSearch) {
      this._reportJump(this._selectionBeforeSearch, this.selection());
      delete this._selectionBeforeSearch;
    }
  }

  /**
   * @param {!Object} highlightDescriptor
   */
  removeHighlight(highlightDescriptor) {
    highlightDescriptor.clear();
  }

  /**
   * @param {!TextUtils.TextRange} range
   * @param {string} cssClass
   * @return {!Object}
   */
  highlightRange(range, cssClass) {
    cssClass = 'CodeMirror-persist-highlight ' + cssClass;
    const pos = TextEditor.CodeMirrorUtils.toPos(range);
    ++pos.end.ch;
    return this.codeMirror().markText(
        pos.start, pos.end, {className: cssClass, startStyle: cssClass + '-start', endStyle: cssClass + '-end'});
  }

  /**
   * @param {string} type
   * @param {boolean} leftToNumbers
   */
  installGutter(type, leftToNumbers) {
    if (this._gutters.indexOf(type) !== -1)
      return;

    if (leftToNumbers)
      this._gutters.unshift(type);
    else
      this._gutters.push(type);

    this.codeMirror().setOption('gutters', this._gutters.slice());
    this.refresh();
  }

  /**
   * @param {string} type
   */
  uninstallGutter(type) {
    const index = this._gutters.indexOf(type);
    if (index === -1)
      return;
    this.codeMirror().clearGutter(type);
    this._gutters.splice(index, 1);
    this.codeMirror().setOption('gutters', this._gutters.slice());
    this.refresh();
  }

  /**
   * @param {number} lineNumber
   * @param {string} type
   * @param {?Element} element
   */
  setGutterDecoration(lineNumber, type, element) {
    console.assert(this._gutters.indexOf(type) !== -1, 'Cannot decorate unexisting gutter.');
    this.codeMirror().setGutterMarker(lineNumber, type, element);
  }

  /**
   * @param {number} lineNumber
   * @param {number} columnNumber
   */
  setExecutionLocation(lineNumber, columnNumber) {
    this.clearPositionHighlight();

    this._executionLine = this.codeMirror().getLineHandle(lineNumber);
    if (!this._executionLine)
      return;

    this.showExecutionLineBackground();
    this.codeMirror().addLineClass(this._executionLine, 'wrap', 'cm-execution-line-outline');
    let token = this.tokenAtTextPosition(lineNumber, columnNumber);

    if (token && !token.type && token.startColumn + 1 === token.endColumn) {
      const tokenContent = this.codeMirror().getLine(lineNumber)[token.startColumn];
      if (tokenContent === '.' || tokenContent === '(')
        token = this.tokenAtTextPosition(lineNumber, token.endColumn + 1);
    }

    let endColumn;
    if (token && token.type)
      endColumn = token.endColumn;
    else
      endColumn = this.codeMirror().getLine(lineNumber).length;

    this._executionLineTailMarker = this.codeMirror().markText(
        {line: lineNumber, ch: columnNumber}, {line: lineNumber, ch: endColumn}, {className: 'cm-execution-line-tail'});
  }

  showExecutionLineBackground() {
    if (this._executionLine)
      this.codeMirror().addLineClass(this._executionLine, 'wrap', 'cm-execution-line');
  }

  hideExecutionLineBackground() {
    if (this._executionLine)
      this.codeMirror().removeLineClass(this._executionLine, 'wrap', 'cm-execution-line');
  }

  clearExecutionLine() {
    this.clearPositionHighlight();

    if (this._executionLine) {
      this.hideExecutionLineBackground();
      this.codeMirror().removeLineClass(this._executionLine, 'wrap', 'cm-execution-line-outline');
    }
    delete this._executionLine;

    if (this._executionLineTailMarker)
      this._executionLineTailMarker.clear();
    delete this._executionLineTailMarker;
  }

  /**
   * @param {number} lineNumber
   * @param {string} className
   * @param {boolean} toggled
   */
  toggleLineClass(lineNumber, className, toggled) {
    if (this.hasLineClass(lineNumber, className) === toggled)
      return;

    const lineHandle = this.codeMirror().getLineHandle(lineNumber);
    if (!lineHandle)
      return;

    if (toggled) {
      this.codeMirror().addLineClass(lineHandle, 'gutter', className);
      this.codeMirror().addLineClass(lineHandle, 'wrap', className);
    } else {
      this.codeMirror().removeLineClass(lineHandle, 'gutter', className);
      this.codeMirror().removeLineClass(lineHandle, 'wrap', className);
    }
  }

  /**
   * @param {number} lineNumber
   * @param {string} className
   * @return {boolean}
   */
  hasLineClass(lineNumber, className) {
    const lineInfo = this.codeMirror().lineInfo(lineNumber);
    const wrapClass = lineInfo.wrapClass || '';
    const classNames = wrapClass.split(' ');
    return classNames.indexOf(className) !== -1;
  }

  _gutterClick(instance, lineNumber, gutter, event) {
    this.dispatchEventToListeners(
        SourceFrame.SourcesTextEditor.Events.GutterClick, {lineNumber: lineNumber, event: event});
  }

  _contextMenu(event) {
    const contextMenu = new UI.ContextMenu(event);
    event.consume(true);  // Consume event now to prevent document from handling the async menu
    const wrapper = event.target.enclosingNodeOrSelfWithClass('CodeMirror-gutter-wrapper');
    const target = wrapper ? wrapper.querySelector('.CodeMirror-linenumber') : null;
    let promise;
    if (target) {
      promise = this._delegate.populateLineGutterContextMenu(contextMenu, parseInt(target.textContent, 10) - 1);
    } else {
      const textSelection = this.selection();
      promise =
          this._delegate.populateTextAreaContextMenu(contextMenu, textSelection.startLine, textSelection.startColumn);
    }
    promise.then(showAsync.bind(this));

    /**
     * @this {SourceFrame.SourcesTextEditor}
     */
    function showAsync() {
      contextMenu.appendApplicableItems(this);
      contextMenu.show();
    }
  }

  /**
   * @override
   * @param {!TextUtils.TextRange} range
   * @param {string} text
   * @param {string=} origin
   * @return {!TextUtils.TextRange}
   */
  editRange(range, text, origin) {
    const newRange = super.editRange(range, text, origin);
    if (Common.moduleSetting('textEditorAutoDetectIndent').get())
      this._onUpdateEditorIndentation();

    return newRange;
  }

  _onUpdateEditorIndentation() {
    this._setEditorIndentation(TextEditor.CodeMirrorUtils.pullLines(
        this.codeMirror(), SourceFrame.SourcesTextEditor.LinesToScanForIndentationGuessing));
  }

  /**
   * @param {!Array.<string>} lines
   */
  _setEditorIndentation(lines) {
    const extraKeys = {};
    let indent = Common.moduleSetting('textEditorIndent').get();
    if (Common.moduleSetting('textEditorAutoDetectIndent').get())
      indent = SourceFrame.SourcesTextEditor._guessIndentationLevel(lines);

    if (indent === TextUtils.TextUtils.Indent.TabCharacter) {
      this.codeMirror().setOption('indentWithTabs', true);
      this.codeMirror().setOption('indentUnit', 4);
    } else {
      this.codeMirror().setOption('indentWithTabs', false);
      this.codeMirror().setOption('indentUnit', indent.length);
      extraKeys.Tab = function(codeMirror) {
        if (codeMirror.somethingSelected())
          return CodeMirror.Pass;
        const pos = codeMirror.getCursor('head');
        codeMirror.replaceRange(indent.substring(pos.ch % indent.length), codeMirror.getCursor());
      };
    }

    this.codeMirror().setOption('extraKeys', extraKeys);
    this._indentationLevel = indent;
  }

  /**
   * @return {string}
   */
  indent() {
    return this._indentationLevel;
  }

  _onAutoAppendedSpaces() {
    this._autoAppendedSpaces = this._autoAppendedSpaces || [];

    for (let i = 0; i < this._autoAppendedSpaces.length; ++i) {
      const position = this._autoAppendedSpaces[i].resolve();
      if (!position)
        continue;
      const line = this.line(position.lineNumber);
      if (line.length === position.columnNumber && TextUtils.TextUtils.lineIndent(line).length === line.length) {
        this.codeMirror().replaceRange(
            '', new CodeMirror.Pos(position.lineNumber, 0),
            new CodeMirror.Pos(position.lineNumber, position.columnNumber));
      }
    }

    this._autoAppendedSpaces = [];
    const selections = this.selections();
    for (let i = 0; i < selections.length; ++i) {
      const selection = selections[i];
      this._autoAppendedSpaces.push(this.textEditorPositionHandle(selection.startLine, selection.startColumn));
    }
  }

  _cursorActivity() {
    if (!this._isSearchActive())
      this.codeMirror().operation(this._tokenHighlighter.highlightSelectedTokens.bind(this._tokenHighlighter));

    const start = this.codeMirror().getCursor('anchor');
    const end = this.codeMirror().getCursor('head');
    this.dispatchEventToListeners(
        SourceFrame.SourcesTextEditor.Events.SelectionChanged, TextEditor.CodeMirrorUtils.toRange(start, end));
  }

  /**
   * @param {?TextUtils.TextRange} from
   * @param {?TextUtils.TextRange} to
   */
  _reportJump(from, to) {
    if (from && to && from.equal(to))
      return;
    this.dispatchEventToListeners(SourceFrame.SourcesTextEditor.Events.JumpHappened, {from: from, to: to});
  }

  _scroll() {
    const topmostLineNumber = this.codeMirror().lineAtHeight(this.codeMirror().getScrollInfo().top, 'local');
    this.dispatchEventToListeners(SourceFrame.SourcesTextEditor.Events.ScrollChanged, topmostLineNumber);
  }

  _focus() {
    this.dispatchEventToListeners(SourceFrame.SourcesTextEditor.Events.EditorFocused);
  }

  _blur() {
    this.dispatchEventToListeners(SourceFrame.SourcesTextEditor.Events.EditorBlurred);
  }

  /**
   * @param {!CodeMirror} codeMirror
   * @param {{ranges: !Array.<{head: !CodeMirror.Pos, anchor: !CodeMirror.Pos}>}} selection
   */
  _fireBeforeSelectionChanged(codeMirror, selection) {
    if (!this._isHandlingMouseDownEvent)
      return;
    if (!selection.ranges.length)
      return;

    const primarySelection = selection.ranges[0];
    this._reportJump(
        this.selection(), TextEditor.CodeMirrorUtils.toRange(primarySelection.anchor, primarySelection.head));
  }

  /**
   * @override
   */
  dispose() {
    super.dispose();
    Common.moduleSetting('textEditorIndent').removeChangeListener(this._onUpdateEditorIndentation, this);
    Common.moduleSetting('textEditorAutoDetectIndent').removeChangeListener(this._onUpdateEditorIndentation, this);
    Common.moduleSetting('showWhitespacesInEditor').removeChangeListener(this._updateWhitespace, this);
  }

  /**
   * @override
   * @param {string} text
   */
  setText(text) {
    this._setEditorIndentation(
        text.split('\n').slice(0, SourceFrame.SourcesTextEditor.LinesToScanForIndentationGuessing));
    super.setText(text);
  }

  _updateWhitespace() {
    this.setMimeType(this.mimeType());
  }

  /**
   * @override
   * @param {string} mimeType
   * @return {string}
   */
  rewriteMimeType(mimeType) {
    this._setupWhitespaceHighlight();
    const whitespaceMode = Common.moduleSetting('showWhitespacesInEditor').get();
    this.element.classList.toggle('show-whitespaces', whitespaceMode === 'all');

    if (whitespaceMode === 'all')
      return this._allWhitespaceOverlayMode(mimeType);
    else if (whitespaceMode === 'trailing')
      return this._trailingWhitespaceOverlayMode(mimeType);

    return mimeType;
  }

  /**
   * @param {string} mimeType
   * @return {string}
   */
  _allWhitespaceOverlayMode(mimeType) {
    let modeName = CodeMirror.mimeModes[mimeType] ?
        (CodeMirror.mimeModes[mimeType].name || CodeMirror.mimeModes[mimeType]) :
        CodeMirror.mimeModes['text/plain'];
    modeName += '+all-whitespaces';
    if (CodeMirror.modes[modeName])
      return modeName;

    function modeConstructor(config, parserConfig) {
      function nextToken(stream) {
        if (stream.peek() === ' ') {
          let spaces = 0;
          while (spaces < SourceFrame.SourcesTextEditor.MaximumNumberOfWhitespacesPerSingleSpan &&
                 stream.peek() === ' ') {
            ++spaces;
            stream.next();
          }
          return 'whitespace whitespace-' + spaces;
        }
        while (!stream.eol() && stream.peek() !== ' ')
          stream.next();
        return null;
      }
      const whitespaceMode = {token: nextToken};
      return CodeMirror.overlayMode(CodeMirror.getMode(config, mimeType), whitespaceMode, false);
    }
    CodeMirror.defineMode(modeName, modeConstructor);
    return modeName;
  }

  /**
   * @param {string} mimeType
   * @return {string}
   */
  _trailingWhitespaceOverlayMode(mimeType) {
    let modeName = CodeMirror.mimeModes[mimeType] ?
        (CodeMirror.mimeModes[mimeType].name || CodeMirror.mimeModes[mimeType]) :
        CodeMirror.mimeModes['text/plain'];
    modeName += '+trailing-whitespaces';
    if (CodeMirror.modes[modeName])
      return modeName;

    function modeConstructor(config, parserConfig) {
      function nextToken(stream) {
        if (stream.match(/^\s+$/, true))
          return true ? 'trailing-whitespace' : null;
        do
          stream.next();
        while (!stream.eol() && stream.peek() !== ' ');
        return null;
      }
      const whitespaceMode = {token: nextToken};
      return CodeMirror.overlayMode(CodeMirror.getMode(config, mimeType), whitespaceMode, false);
    }
    CodeMirror.defineMode(modeName, modeConstructor);
    return modeName;
  }

  _setupWhitespaceHighlight() {
    const doc = this.element.ownerDocument;
    if (doc._codeMirrorWhitespaceStyleInjected || !Common.moduleSetting('showWhitespacesInEditor').get())
      return;
    doc._codeMirrorWhitespaceStyleInjected = true;
    const classBase = '.show-whitespaces .CodeMirror .cm-whitespace-';
    const spaceChar = '·';
    let spaceChars = '';
    let rules = '';
    for (let i = 1; i <= SourceFrame.SourcesTextEditor.MaximumNumberOfWhitespacesPerSingleSpan; ++i) {
      spaceChars += spaceChar;
      const rule = classBase + i + '::before { content: \'' + spaceChars + '\';}\n';
      rules += rule;
    }
    const style = doc.createElement('style');
    style.textContent = rules;
    doc.head.appendChild(style);
  }

  /**
   * @override
   * @param {?UI.AutocompleteConfig} config
   */
  configureAutocomplete(config) {
    this._autocompleteConfig = config;
    this._updateAutocomplete();
  }

  _updateAutocomplete() {
    super.configureAutocomplete(
        Common.moduleSetting('textEditorAutocompletion').get() ? this._autocompleteConfig : null);
  }
};

/** @typedef {{lineNumber: number, event: !Event}} */
SourceFrame.SourcesTextEditor.GutterClickEventData;

/** @enum {symbol} */
SourceFrame.SourcesTextEditor.Events = {
  GutterClick: Symbol('GutterClick'),
  SelectionChanged: Symbol('SelectionChanged'),
  ScrollChanged: Symbol('ScrollChanged'),
  EditorFocused: Symbol('EditorFocused'),
  EditorBlurred: Symbol('EditorBlurred'),
  JumpHappened: Symbol('JumpHappened')
};

/**
 * @interface
 */
SourceFrame.SourcesTextEditorDelegate = function() {};
SourceFrame.SourcesTextEditorDelegate.prototype = {
  /**
   * @param {!UI.ContextMenu} contextMenu
   * @param {number} lineNumber
   * @return {!Promise}
   */
  populateLineGutterContextMenu(contextMenu, lineNumber) {},

  /**
   * @param {!UI.ContextMenu} contextMenu
   * @param {number} lineNumber
   * @param {number} columnNumber
   * @return {!Promise}
   */
  populateTextAreaContextMenu(contextMenu, lineNumber, columnNumber) {},
};

/**
 * @param {!CodeMirror} codeMirror
 */
CodeMirror.commands.smartNewlineAndIndent = function(codeMirror) {
  codeMirror.operation(innerSmartNewlineAndIndent.bind(null, codeMirror));
  function innerSmartNewlineAndIndent(codeMirror) {
    const selections = codeMirror.listSelections();
    const replacements = [];
    for (let i = 0; i < selections.length; ++i) {
      const selection = selections[i];
      const cur = CodeMirror.cmpPos(selection.head, selection.anchor) < 0 ? selection.head : selection.anchor;
      const line = codeMirror.getLine(cur.line);
      const indent = TextUtils.TextUtils.lineIndent(line);
      replacements.push('\n' + indent.substring(0, Math.min(cur.ch, indent.length)));
    }
    codeMirror.replaceSelections(replacements);
    codeMirror._codeMirrorTextEditor._onAutoAppendedSpaces();
  }
};

/**
 * @return {!Object|undefined}
 */
CodeMirror.commands.sourcesDismiss = function(codemirror) {
  if (codemirror.listSelections().length === 1 && codemirror._codeMirrorTextEditor._isSearchActive())
    return CodeMirror.Pass;
  return CodeMirror.commands.dismiss(codemirror);
};

SourceFrame.SourcesTextEditor._BlockIndentController = {
  name: 'blockIndentKeymap',

  /**
   * @return {*}
   */
  Enter: function(codeMirror) {
    let selections = codeMirror.listSelections();
    const replacements = [];
    let allSelectionsAreCollapsedBlocks = false;
    for (let i = 0; i < selections.length; ++i) {
      const selection = selections[i];
      const start = CodeMirror.cmpPos(selection.head, selection.anchor) < 0 ? selection.head : selection.anchor;
      const line = codeMirror.getLine(start.line);
      const indent = TextUtils.TextUtils.lineIndent(line);
      let indentToInsert = '\n' + indent + codeMirror._codeMirrorTextEditor.indent();
      let isCollapsedBlock = false;
      if (selection.head.ch === 0)
        return CodeMirror.Pass;
      if (line.substr(selection.head.ch - 1, 2) === '{}') {
        indentToInsert += '\n' + indent;
        isCollapsedBlock = true;
      } else if (line.substr(selection.head.ch - 1, 1) !== '{') {
        return CodeMirror.Pass;
      }
      if (i > 0 && allSelectionsAreCollapsedBlocks !== isCollapsedBlock)
        return CodeMirror.Pass;
      replacements.push(indentToInsert);
      allSelectionsAreCollapsedBlocks = isCollapsedBlock;
    }
    codeMirror.replaceSelections(replacements);
    if (!allSelectionsAreCollapsedBlocks) {
      codeMirror._codeMirrorTextEditor._onAutoAppendedSpaces();
      return;
    }
    selections = codeMirror.listSelections();
    const updatedSelections = [];
    for (let i = 0; i < selections.length; ++i) {
      const selection = selections[i];
      const line = codeMirror.getLine(selection.head.line - 1);
      const position = new CodeMirror.Pos(selection.head.line - 1, line.length);
      updatedSelections.push({head: position, anchor: position});
    }
    codeMirror.setSelections(updatedSelections);
    codeMirror._codeMirrorTextEditor._onAutoAppendedSpaces();
  },

  /**
   * @return {*}
   */
  '\'}\'': function(codeMirror) {
    if (codeMirror.somethingSelected())
      return CodeMirror.Pass;
    let selections = codeMirror.listSelections();
    let replacements = [];
    for (let i = 0; i < selections.length; ++i) {
      const selection = selections[i];
      const line = codeMirror.getLine(selection.head.line);
      if (line !== TextUtils.TextUtils.lineIndent(line))
        return CodeMirror.Pass;
      replacements.push('}');
    }
    codeMirror.replaceSelections(replacements);
    selections = codeMirror.listSelections();
    replacements = [];
    const updatedSelections = [];
    for (let i = 0; i < selections.length; ++i) {
      const selection = selections[i];
      const matchingBracket = codeMirror.findMatchingBracket(selection.head);
      if (!matchingBracket || !matchingBracket.match)
        return;
      updatedSelections.push({head: selection.head, anchor: new CodeMirror.Pos(selection.head.line, 0)});
      const line = codeMirror.getLine(matchingBracket.to.line);
      const indent = TextUtils.TextUtils.lineIndent(line);
      replacements.push(indent + '}');
    }
    codeMirror.setSelections(updatedSelections);
    codeMirror.replaceSelections(replacements);
  }
};


/**
 * @unrestricted
 */
SourceFrame.SourcesTextEditor.TokenHighlighter = class {
  /**
   * @param {!SourceFrame.SourcesTextEditor} textEditor
   * @param {!CodeMirror} codeMirror
   */
  constructor(textEditor, codeMirror) {
    this._textEditor = textEditor;
    this._codeMirror = codeMirror;
  }

  /**
   * @param {!RegExp} regex
   * @param {?TextUtils.TextRange} range
   */
  highlightSearchResults(regex, range) {
    const oldRegex = this._highlightRegex;
    this._highlightRegex = regex;
    this._highlightRange = range;
    if (this._searchResultMarker) {
      this._searchResultMarker.clear();
      delete this._searchResultMarker;
    }
    if (this._highlightDescriptor && this._highlightDescriptor.selectionStart)
      this._codeMirror.removeLineClass(this._highlightDescriptor.selectionStart.line, 'wrap', 'cm-line-with-selection');
    const selectionStart = this._highlightRange ?
        new CodeMirror.Pos(this._highlightRange.startLine, this._highlightRange.startColumn) :
        null;
    if (selectionStart)
      this._codeMirror.addLineClass(selectionStart.line, 'wrap', 'cm-line-with-selection');
    if (oldRegex && this._highlightRegex.toString() === oldRegex.toString()) {
      // Do not re-add overlay mode if regex did not change for better performance.
      if (this._highlightDescriptor)
        this._highlightDescriptor.selectionStart = selectionStart;
    } else {
      this._removeHighlight();
      this._setHighlighter(this._searchHighlighter.bind(this, this._highlightRegex), selectionStart);
    }
    if (this._highlightRange) {
      const pos = TextEditor.CodeMirrorUtils.toPos(this._highlightRange);
      this._searchResultMarker = this._codeMirror.markText(pos.start, pos.end, {className: 'cm-column-with-selection'});
    }
  }

  /**
   * @return {!RegExp|undefined}
   */
  highlightedRegex() {
    return this._highlightRegex;
  }

  highlightSelectedTokens() {
    delete this._highlightRegex;
    delete this._highlightRange;
    if (this._highlightDescriptor && this._highlightDescriptor.selectionStart)
      this._codeMirror.removeLineClass(this._highlightDescriptor.selectionStart.line, 'wrap', 'cm-line-with-selection');
    this._removeHighlight();
    const selectionStart = this._codeMirror.getCursor('start');
    const selectionEnd = this._codeMirror.getCursor('end');
    if (selectionStart.line !== selectionEnd.line)
      return;
    if (selectionStart.ch === selectionEnd.ch)
      return;
    const selections = this._codeMirror.getSelections();
    if (selections.length > 1)
      return;
    const selectedText = selections[0];
    if (this._isWord(selectedText, selectionStart.line, selectionStart.ch, selectionEnd.ch)) {
      if (selectionStart)
        this._codeMirror.addLineClass(selectionStart.line, 'wrap', 'cm-line-with-selection');
      this._setHighlighter(this._tokenHighlighter.bind(this, selectedText, selectionStart), selectionStart);
    }
  }

  /**
   * @param {string} selectedText
   * @param {number} lineNumber
   * @param {number} startColumn
   * @param {number} endColumn
   */
  _isWord(selectedText, lineNumber, startColumn, endColumn) {
    const line = this._codeMirror.getLine(lineNumber);
    const leftBound = startColumn === 0 || !TextUtils.TextUtils.isWordChar(line.charAt(startColumn - 1));
    const rightBound = endColumn === line.length || !TextUtils.TextUtils.isWordChar(line.charAt(endColumn));
    return leftBound && rightBound && TextUtils.TextUtils.isWord(selectedText);
  }

  _removeHighlight() {
    if (this._highlightDescriptor) {
      this._codeMirror.removeOverlay(this._highlightDescriptor.overlay);
      delete this._highlightDescriptor;
    }
  }

  /**
   * @param {!RegExp} regex
   * @param {!CodeMirror.StringStream} stream
   */
  _searchHighlighter(regex, stream) {
    if (stream.column() === 0)
      delete this._searchMatchLength;
    if (this._searchMatchLength) {
      if (this._searchMatchLength > 2) {
        for (let i = 0; i < this._searchMatchLength - 2; ++i)
          stream.next();
        this._searchMatchLength = 1;
        return 'search-highlight';
      } else {
        stream.next();
        delete this._searchMatchLength;
        return 'search-highlight search-highlight-end';
      }
    }
    const match = stream.match(regex, false);
    if (match) {
      stream.next();
      const matchLength = match[0].length;
      if (matchLength === 1)
        return 'search-highlight search-highlight-full';
      this._searchMatchLength = matchLength;
      return 'search-highlight search-highlight-start';
    }
    while (!stream.match(regex, false) && stream.next()) {
    }
  }

  /**
   * @param {string} token
   * @param {!CodeMirror.Pos} selectionStart
   * @param {!CodeMirror.StringStream} stream
   */
  _tokenHighlighter(token, selectionStart, stream) {
    const tokenFirstChar = token.charAt(0);
    if (stream.match(token) && (stream.eol() || !TextUtils.TextUtils.isWordChar(stream.peek())))
      return stream.column() === selectionStart.ch ? 'token-highlight column-with-selection' : 'token-highlight';
    let eatenChar;
    do
      eatenChar = stream.next();
    while (eatenChar && (TextUtils.TextUtils.isWordChar(eatenChar) || stream.peek() !== tokenFirstChar));
  }

  /**
   * @param {function(!CodeMirror.StringStream)} highlighter
   * @param {?CodeMirror.Pos} selectionStart
   */
  _setHighlighter(highlighter, selectionStart) {
    const overlayMode = {token: highlighter};
    this._codeMirror.addOverlay(overlayMode);
    this._highlightDescriptor = {overlay: overlayMode, selectionStart: selectionStart};
  }
};

SourceFrame.SourcesTextEditor.LinesToScanForIndentationGuessing = 1000;
SourceFrame.SourcesTextEditor.MaximumNumberOfWhitespacesPerSingleSpan = 16;
