/*
 * Copyright (C) 2012 Google 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * OWNER OR 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.
 */

/**
 * @implements {UI.TextEditor}
 * @unrestricted
 */
export class CodeMirrorTextEditor extends UI.VBox {
  /**
   * @param {!UI.TextEditor.Options} options
   */
  constructor(options) {
    super();
    this._options = options;

    this.registerRequiredCSS('cm/codemirror.css');
    this.registerRequiredCSS('text_editor/cmdevtools.css');

    const {indentWithTabs, indentUnit} =
        CodeMirrorTextEditor._getIndentation(Common.moduleSetting('textEditorIndent').get());

    this._codeMirror = new CodeMirror(this.element, {
      devtoolsAccessibleName: options.devtoolsAccessibleName,
      lineNumbers: options.lineNumbers,
      matchBrackets: true,
      smartIndent: true,
      styleSelectedText: true,
      electricChars: true,
      styleActiveLine: true,
      indentUnit,
      indentWithTabs,
      lineWrapping: options.lineWrapping,
      lineWiseCopyCut: false,
      tabIndex: 0,
      pollInterval: Math.pow(2, 31) - 1,  // ~25 days
      inputStyle: 'devToolsAccessibleTextArea'
    });
    this._codeMirrorElement = this.element.lastElementChild;

    this._codeMirror._codeMirrorTextEditor = this;

    Common.moduleSetting('textEditorIndent').addChangeListener(this._updateIndentSize.bind(this));

    CodeMirror.keyMap['devtools-common'] = {
      'Left': 'goCharLeft',
      'Right': 'goCharRight',
      'Up': 'goLineUp',
      'Down': 'goLineDown',
      'End': 'goLineEnd',
      'Home': 'goLineStartSmart',
      'PageUp': 'goSmartPageUp',
      'PageDown': 'goSmartPageDown',
      'Delete': 'delCharAfter',
      'Backspace': 'delCharBefore',
      'Tab': 'UserIndent',
      'Shift-Tab': 'indentLessOrPass',
      'Enter': 'newlineAndIndent',
      'Ctrl-Space': 'autocomplete',
      'Esc': 'dismiss',
      'Ctrl-M': 'gotoMatchingBracket'
    };

    CodeMirror.keyMap['devtools-pc'] = {
      'Ctrl-A': 'selectAll',
      'Ctrl-Z': 'undoAndReveal',
      'Shift-Ctrl-Z': 'redoAndReveal',
      'Ctrl-Y': 'redo',
      'Ctrl-Home': 'goDocStart',
      'Ctrl-Up': 'goDocStart',
      'Ctrl-End': 'goDocEnd',
      'Ctrl-Down': 'goDocEnd',
      'Ctrl-Left': 'goGroupLeft',
      'Ctrl-Right': 'goGroupRight',
      'Alt-Left': 'moveCamelLeft',
      'Alt-Right': 'moveCamelRight',
      'Shift-Alt-Left': 'selectCamelLeft',
      'Shift-Alt-Right': 'selectCamelRight',
      'Ctrl-Backspace': 'delGroupBefore',
      'Ctrl-Delete': 'delGroupAfter',
      'Ctrl-/': 'toggleComment',
      'Ctrl-D': 'selectNextOccurrence',
      'Ctrl-U': 'undoLastSelection',
      fallthrough: 'devtools-common'
    };

    CodeMirror.keyMap['devtools-mac'] = {
      'Cmd-A': 'selectAll',
      'Cmd-Z': 'undoAndReveal',
      'Shift-Cmd-Z': 'redoAndReveal',
      'Cmd-Up': 'goDocStart',
      'Cmd-Down': 'goDocEnd',
      'Alt-Left': 'goGroupLeft',
      'Alt-Right': 'goGroupRight',
      'Ctrl-Left': 'moveCamelLeft',
      'Ctrl-Right': 'moveCamelRight',
      'Ctrl-A': 'goLineLeft',
      'Ctrl-E': 'goLineRight',
      'Ctrl-B': 'goCharLeft',
      'Ctrl-F': 'goCharRight',
      'Ctrl-Alt-B': 'goGroupLeft',
      'Ctrl-Alt-F': 'goGroupRight',
      'Ctrl-H': 'delCharBefore',
      'Ctrl-D': 'delCharAfter',
      'Ctrl-K': 'killLine',
      'Ctrl-T': 'transposeChars',
      'Ctrl-P': 'goLineUp',
      'Ctrl-N': 'goLineDown',
      'Shift-Ctrl-Left': 'selectCamelLeft',
      'Shift-Ctrl-Right': 'selectCamelRight',
      'Cmd-Left': 'goLineStartSmart',
      'Cmd-Right': 'goLineEnd',
      'Cmd-Backspace': 'delLineLeft',
      'Alt-Backspace': 'delGroupBefore',
      'Alt-Delete': 'delGroupAfter',
      'Cmd-/': 'toggleComment',
      'Cmd-D': 'selectNextOccurrence',
      'Cmd-U': 'undoLastSelection',
      fallthrough: 'devtools-common'
    };

    if (options.bracketMatchingSetting) {
      options.bracketMatchingSetting.addChangeListener(this._enableBracketMatchingIfNeeded, this);
    }
    this._enableBracketMatchingIfNeeded();

    this._codeMirror.setOption('keyMap', Host.isMac() ? 'devtools-mac' : 'devtools-pc');

    this._codeMirror.setOption('flattenSpans', false);

    let maxHighlightLength = options.maxHighlightLength;
    if (typeof maxHighlightLength !== 'number') {
      maxHighlightLength = CodeMirrorTextEditor.maxHighlightLength;
    }
    this._codeMirror.setOption('maxHighlightLength', maxHighlightLength);
    this._codeMirror.setOption('mode', null);
    this._codeMirror.setOption('crudeMeasuringFrom', 1000);

    this._shouldClearHistory = true;
    this._lineSeparator = '\n';

    CodeMirrorTextEditor._fixWordMovement(this._codeMirror);

    this._selectNextOccurrenceController = new SelectNextOccurrenceController(this, this._codeMirror);

    this._codeMirror.on('changes', this._changes.bind(this));
    this._codeMirror.on('beforeSelectionChange', this._beforeSelectionChange.bind(this));
    this._codeMirror.on('cursorActivity', () => {
      this.dispatchEventToListeners(UI.TextEditor.Events.CursorChanged);
    });

    this.element.style.overflow = 'hidden';
    this._codeMirrorElement.classList.add('source-code');
    this._codeMirrorElement.classList.add('fill');

    /** @type {!Platform.Multimap<number, !TextEditor.CodeMirrorTextEditor.Decoration>} */
    this._decorations = new Platform.Multimap();

    this.element.addEventListener('keydown', this._handleKeyDown.bind(this), true);
    this.element.addEventListener('keydown', this._handlePostKeyDown.bind(this), false);

    this._needsRefresh = true;

    this._readOnly = false;

    this._mimeType = '';
    if (options.mimeType) {
      this.setMimeType(options.mimeType);
    }
    if (options.autoHeight) {
      this._codeMirror.setSize(null, 'auto');
    }

    this._placeholderElement = null;
    if (options.placeholder) {
      this._placeholderElement = createElement('pre');
      this._placeholderElement.classList.add('placeholder-text');
      this._placeholderElement.textContent = options.placeholder;
      this._updatePlaceholder();
    }
  }

  /**
   * @param {!CodeMirror} codeMirror
   */
  static autocompleteCommand(codeMirror) {
    const autocompleteController = codeMirror._codeMirrorTextEditor._autocompleteController;
    if (autocompleteController) {
      autocompleteController.autocomplete(true);
    }
  }

  /**
   * @param {!CodeMirror} codeMirror
   */
  static undoLastSelectionCommand(codeMirror) {
    codeMirror._codeMirrorTextEditor._selectNextOccurrenceController.undoLastSelection();
  }

  /**
   * @param {!CodeMirror} codeMirror
   */
  static selectNextOccurrenceCommand(codeMirror) {
    codeMirror._codeMirrorTextEditor._selectNextOccurrenceController.selectNextOccurrence();
  }

  /**
   * @param {boolean} shift
   * @param {!CodeMirror} codeMirror
   */
  static moveCamelLeftCommand(shift, codeMirror) {
    codeMirror._codeMirrorTextEditor._doCamelCaseMovement(-1, shift);
  }

  /**
   * @param {boolean} shift
   * @param {!CodeMirror} codeMirror
   */
  static moveCamelRightCommand(shift, codeMirror) {
    codeMirror._codeMirrorTextEditor._doCamelCaseMovement(1, shift);
  }

  /**
   * @param {string} indentationValue
   */
  static _getIndentation(indentationValue) {
    const indentWithTabs = /\t/.test(indentationValue);
    const indentUnit = indentWithTabs ? 4 : indentationValue.length;
    return {indentWithTabs, indentUnit};
  }

  /**
   * @param {string} modeName
   * @param {string} tokenPrefix
   */
  static _overrideModeWithPrefixedTokens(modeName, tokenPrefix) {
    const oldModeName = modeName + '-old';
    if (CodeMirror.modes[oldModeName]) {
      return;
    }

    CodeMirror.defineMode(oldModeName, CodeMirror.modes[modeName]);
    CodeMirror.defineMode(modeName, modeConstructor);

    function modeConstructor(config, parserConfig) {
      const innerConfig = {};
      for (const i in parserConfig) {
        innerConfig[i] = parserConfig[i];
      }
      innerConfig.name = oldModeName;
      const codeMirrorMode = CodeMirror.getMode(config, innerConfig);
      codeMirrorMode.name = modeName;
      codeMirrorMode.token = tokenOverride.bind(null, codeMirrorMode.token);
      return codeMirrorMode;
    }

    function tokenOverride(superToken, stream, state) {
      const token = superToken(stream, state);
      return token ? tokenPrefix + token.split(/ +/).join(' ' + tokenPrefix) : token;
    }
  }

  /**
   * @param {string} mimeType
   * @return {!Array<!Root.Runtime.Extension>}}
   */
  static _collectUninstalledModes(mimeType) {
    const installed = _loadedMimeModeExtensions;

    const nameToExtension = new Map();
    const extensions = self.runtime.extensions(CodeMirrorMimeMode);
    for (const extension of extensions) {
      nameToExtension.set(extension.descriptor()['fileName'], extension);
    }

    const modesToLoad = new Set();
    for (const extension of extensions) {
      const descriptor = extension.descriptor();
      if (installed.has(extension) || descriptor['mimeTypes'].indexOf(mimeType) === -1) {
        continue;
      }

      modesToLoad.add(extension);
      const deps = descriptor['dependencies'] || [];
      for (let i = 0; i < deps.length; ++i) {
        const extension = nameToExtension.get(deps[i]);
        if (extension && !installed.has(extension)) {
          modesToLoad.add(extension);
        }
      }
    }
    return Array.from(modesToLoad);
  }

  /**
   * @param {!Array<!Root.Runtime.Extension>} extensions
   * @return {!Promise}
   */
  static _installMimeTypeModes(extensions) {
    const promises = extensions.map(extension => extension.instance().then(installMode.bind(null, extension)));
    return Promise.all(promises);

    /**
     * @param {!Root.Runtime.Extension} extension
     * @param {!Object} instance
     */
    function installMode(extension, instance) {
      if (_loadedMimeModeExtensions.has(extension)) {
        return;
      }
      const mode = /** @type {!CodeMirrorMimeMode} */ (instance);
      mode.install(extension);
      _loadedMimeModeExtensions.add(extension);
    }
  }

  /**
   * @param {!CodeMirror} codeMirror
   */
  static _fixWordMovement(codeMirror) {
    function moveLeft(shift, codeMirror) {
      codeMirror.setExtending(shift);
      const cursor = codeMirror.getCursor('head');
      codeMirror.execCommand('goGroupLeft');
      const newCursor = codeMirror.getCursor('head');
      if (newCursor.ch === 0 && newCursor.line !== 0) {
        codeMirror.setExtending(false);
        return;
      }

      const skippedText = codeMirror.getRange(newCursor, cursor, '#');
      if (/^\s+$/.test(skippedText)) {
        codeMirror.execCommand('goGroupLeft');
      }
      codeMirror.setExtending(false);
    }

    function moveRight(shift, codeMirror) {
      codeMirror.setExtending(shift);
      const cursor = codeMirror.getCursor('head');
      codeMirror.execCommand('goGroupRight');
      const newCursor = codeMirror.getCursor('head');
      if (newCursor.ch === 0 && newCursor.line !== 0) {
        codeMirror.setExtending(false);
        return;
      }

      const skippedText = codeMirror.getRange(cursor, newCursor, '#');
      if (/^\s+$/.test(skippedText)) {
        codeMirror.execCommand('goGroupRight');
      }
      codeMirror.setExtending(false);
    }

    const modifierKey = Host.isMac() ? 'Alt' : 'Ctrl';
    const leftKey = modifierKey + '-Left';
    const rightKey = modifierKey + '-Right';
    const keyMap = {};
    keyMap[leftKey] = moveLeft.bind(null, false);
    keyMap[rightKey] = moveRight.bind(null, false);
    keyMap['Shift-' + leftKey] = moveLeft.bind(null, true);
    keyMap['Shift-' + rightKey] = moveRight.bind(null, true);
    codeMirror.addKeyMap(keyMap);
  }

  /**
   * @protected
   * @return {!CodeMirror}
   */
  codeMirror() {
    return this._codeMirror;
  }

  /**
   * @override
   * @return {!UI.Widget}
   */
  widget() {
    return this;
  }

  /**
   * @override
   * @param {string} placeholder
   */
  setPlaceholder(placeholder) {
    if (!this._placeholderElement) {
      this._placeholderElement = createElement('pre');
      this._placeholderElement.classList.add('placeholder-text');
    }
    this._placeholderElement.textContent = placeholder || '';
    this._updatePlaceholder();
  }

  /**
   * @param {number} lineNumber
   * @param {number} lineLength
   * @param {number} charNumber
   * @return {{lineNumber: number, columnNumber: number}}
   */
  _normalizePositionForOverlappingColumn(lineNumber, lineLength, charNumber) {
    const linesCount = this._codeMirror.lineCount();
    let columnNumber = charNumber;
    if (charNumber < 0 && lineNumber > 0) {
      --lineNumber;
      columnNumber = this.line(lineNumber).length;
    } else if (charNumber >= lineLength && lineNumber < linesCount - 1) {
      ++lineNumber;
      columnNumber = 0;
    } else {
      columnNumber = Number.constrain(charNumber, 0, lineLength);
    }
    return {lineNumber: lineNumber, columnNumber: columnNumber};
  }

  /**
   * @param {number} lineNumber
   * @param {number} columnNumber
   * @param {number} direction
   * @return {{lineNumber: number, columnNumber: number}}
   */
  _camelCaseMoveFromPosition(lineNumber, columnNumber, direction) {
    /**
     * @param {number} charNumber
     * @param {number} length
     * @return {boolean}
     */
    function valid(charNumber, length) {
      return charNumber >= 0 && charNumber < length;
    }

    /**
     * @param {string} text
     * @param {number} charNumber
     * @return {boolean}
     */
    function isWordStart(text, charNumber) {
      const position = charNumber;
      const nextPosition = charNumber + 1;
      return valid(position, text.length) && valid(nextPosition, text.length) &&
          TextUtils.TextUtils.isWordChar(text[position]) && TextUtils.TextUtils.isWordChar(text[nextPosition]) &&
          TextUtils.TextUtils.isUpperCase(text[position]) && TextUtils.TextUtils.isLowerCase(text[nextPosition]);
    }

    /**
     * @param {string} text
     * @param {number} charNumber
     * @return {boolean}
     */
    function isWordEnd(text, charNumber) {
      const position = charNumber;
      const prevPosition = charNumber - 1;
      return valid(position, text.length) && valid(prevPosition, text.length) &&
          TextUtils.TextUtils.isWordChar(text[position]) && TextUtils.TextUtils.isWordChar(text[prevPosition]) &&
          TextUtils.TextUtils.isUpperCase(text[position]) && TextUtils.TextUtils.isLowerCase(text[prevPosition]);
    }

    /**
     * @param {number} lineNumber
     * @param {number} lineLength
     * @param {number} columnNumber
     * @return {{lineNumber: number, columnNumber: number}}
     */
    function constrainPosition(lineNumber, lineLength, columnNumber) {
      return {lineNumber: lineNumber, columnNumber: Number.constrain(columnNumber, 0, lineLength)};
    }

    const text = this.line(lineNumber);
    const length = text.length;

    if ((columnNumber === length && direction === 1) || (columnNumber === 0 && direction === -1)) {
      return this._normalizePositionForOverlappingColumn(lineNumber, length, columnNumber + direction);
    }

    let charNumber = direction === 1 ? columnNumber : columnNumber - 1;

    // Move through initial spaces if any.
    while (valid(charNumber, length) && TextUtils.TextUtils.isSpaceChar(text[charNumber])) {
      charNumber += direction;
    }
    if (!valid(charNumber, length)) {
      return constrainPosition(lineNumber, length, charNumber);
    }

    if (TextUtils.TextUtils.isStopChar(text[charNumber])) {
      while (valid(charNumber, length) && TextUtils.TextUtils.isStopChar(text[charNumber])) {
        charNumber += direction;
      }
      if (!valid(charNumber, length)) {
        return constrainPosition(lineNumber, length, charNumber);
      }
      return {lineNumber: lineNumber, columnNumber: direction === -1 ? charNumber + 1 : charNumber};
    }

    charNumber += direction;
    while (valid(charNumber, length) && !isWordStart(text, charNumber) && !isWordEnd(text, charNumber) &&
           TextUtils.TextUtils.isWordChar(text[charNumber])) {
      charNumber += direction;
    }

    if (!valid(charNumber, length)) {
      return constrainPosition(lineNumber, length, charNumber);
    }
    if (isWordStart(text, charNumber) || isWordEnd(text, charNumber)) {
      return {lineNumber: lineNumber, columnNumber: charNumber};
    }


    return {lineNumber: lineNumber, columnNumber: direction === -1 ? charNumber + 1 : charNumber};
  }

  /**
   * @param {number} direction
   * @param {boolean} shift
   */
  _doCamelCaseMovement(direction, shift) {
    const selections = this.selections();
    for (let i = 0; i < selections.length; ++i) {
      const selection = selections[i];
      const move = this._camelCaseMoveFromPosition(selection.endLine, selection.endColumn, direction);
      selection.endLine = move.lineNumber;
      selection.endColumn = move.columnNumber;
      if (!shift) {
        selections[i] = selection.collapseToEnd();
      }
    }
    this.setSelections(selections);
  }

  dispose() {
    if (this._options.bracketMatchingSetting) {
      this._options.bracketMatchingSetting.removeChangeListener(this._enableBracketMatchingIfNeeded, this);
    }
  }

  _enableBracketMatchingIfNeeded() {
    this._codeMirror.setOption(
        'autoCloseBrackets', (this._options.bracketMatchingSetting && this._options.bracketMatchingSetting.get()) ?
            {explode: false} :
            false);
  }

  /**
   * @override
   */
  wasShown() {
    if (this._needsRefresh) {
      this.refresh();
    }
  }

  /**
   * @protected
   */
  refresh() {
    if (this.isShowing()) {
      this._codeMirror.refresh();
      this._needsRefresh = false;
      return;
    }
    this._needsRefresh = true;
  }

  /**
   * @override
   */
  willHide() {
    delete this._editorSizeInSync;
  }

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

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

  /**
   * @param {!Event} e
   */
  _handleKeyDown(e) {
    if (e.key === 'Tab' && Common.moduleSetting('textEditorTabMovesFocus').get()) {
      e.consume(false);
      return;
    }
    if (this._autocompleteController && this._autocompleteController.keyDown(e)) {
      e.consume(true);
    }
  }

  /**
   * @param {!Event} e
   */
  _handlePostKeyDown(e) {
    if (e.defaultPrevented) {
      e.consume(true);
    }
  }

  /**
   * @override
   * @param {?UI.AutocompleteConfig} config
   */
  configureAutocomplete(config) {
    if (this._autocompleteController) {
      this._autocompleteController.dispose();
      delete this._autocompleteController;
    }

    if (config) {
      this._autocompleteController = new TextEditor.TextEditorAutocompleteController(this, this._codeMirror, config);
    }
  }

  /**
   * @param {number} lineNumber
   * @param {number} column
   * @return {?{x: number, y: number, height: number}}
   */
  cursorPositionToCoordinates(lineNumber, column) {
    if (lineNumber >= this._codeMirror.lineCount() || lineNumber < 0 || column < 0 ||
        column > this._codeMirror.getLine(lineNumber).length) {
      return null;
    }
    const metrics = this._codeMirror.cursorCoords(new CodeMirror.Pos(lineNumber, column));
    return {x: metrics.left, y: metrics.top, height: metrics.bottom - metrics.top};
  }

  /**
   * @param {number} x
   * @param {number} y
   * @return {?TextUtils.TextRange}
   */
  coordinatesToCursorPosition(x, y) {
    const element = this.element.ownerDocument.elementFromPoint(x, y);
    if (!element || !element.isSelfOrDescendant(this._codeMirror.getWrapperElement())) {
      return null;
    }
    const gutterBox = this._codeMirror.getGutterElement().boxInWindow();
    if (x >= gutterBox.x && x <= gutterBox.x + gutterBox.width && y >= gutterBox.y &&
        y <= gutterBox.y + gutterBox.height) {
      return null;
    }
    const coords = this._codeMirror.coordsChar({left: x, top: y});
    return TextEditor.CodeMirrorUtils.toRange(coords, coords);
  }

  /**
   * @override
   * @param {number} lineNumber
   * @param {number} columnNumber
   * @return {!{x: number, y: number}}
   */
  visualCoordinates(lineNumber, columnNumber) {
    const metrics = this._codeMirror.cursorCoords(new CodeMirror.Pos(lineNumber, columnNumber));
    return {x: metrics.left, y: metrics.top};
  }

  /**
   * @override
   * @param {number} lineNumber
   * @param {number} columnNumber
   * @return {?{startColumn: number, endColumn: number, type: string}}
   */
  tokenAtTextPosition(lineNumber, columnNumber) {
    if (lineNumber < 0 || lineNumber >= this._codeMirror.lineCount()) {
      return null;
    }
    const token = this._codeMirror.getTokenAt(new CodeMirror.Pos(lineNumber, (columnNumber || 0) + 1));
    if (!token) {
      return null;
    }
    return {startColumn: token.start, endColumn: token.end, type: token.type};
  }

  /**
   * @param {number} generation
   * @return {boolean}
   */
  isClean(generation) {
    return this._codeMirror.isClean(generation);
  }

  /**
   * @return {number}
   */
  markClean() {
    return this._codeMirror.changeGeneration(true);
  }

  /**
   * @return {boolean}
   */
  _hasLongLines() {
    function lineIterator(lineHandle) {
      if (lineHandle.text.length > CodeMirrorTextEditor.LongLineModeLineLengthThreshold) {
        hasLongLines = true;
      }
      return hasLongLines;
    }
    let hasLongLines = false;
    this._codeMirror.eachLine(lineIterator);
    return hasLongLines;
  }

  _enableLongLinesMode() {
    this._codeMirror.setOption('styleSelectedText', false);
  }

  _disableLongLinesMode() {
    this._codeMirror.setOption('styleSelectedText', true);
  }

  /**
   * @param {!{data: *}} updatedValue
   */
  _updateIndentSize(updatedValue) {
    const {indentWithTabs, indentUnit} =
        CodeMirrorTextEditor._getIndentation(/** @type {string} */ (updatedValue.data));

    this._codeMirror.setOption('indentUnit', indentUnit);
    this._codeMirror.setOption('indentWithTabs', indentWithTabs);
  }

  /**
   * @param {string} mimeType
   */
  setMimeType(mimeType) {
    this._mimeType = mimeType;
    const modesToLoad = CodeMirrorTextEditor._collectUninstalledModes(mimeType);

    if (!modesToLoad.length) {
      setMode.call(this);
    } else {
      CodeMirrorTextEditor._installMimeTypeModes(modesToLoad).then(setMode.bind(this));
    }

    /**
     * @this {CodeMirrorTextEditor}
     */
    function setMode() {
      const rewrittenMimeType = this.rewriteMimeType(mimeType);
      if (this._codeMirror.options.mode !== rewrittenMimeType) {
        this._codeMirror.setOption('mode', rewrittenMimeType);
      }
    }
  }

  /**
   * @param {!Object} mode
   */
  setHighlightMode(mode) {
    this._mimeType = '';
    this._codeMirror.setOption('mode', mode);
  }

  /**
   * @protected
   * @param {string} mimeType
   */
  rewriteMimeType(mimeType) {
    // Overridden in SourcesTextEditor
    return mimeType;
  }

  /**
   * @protected
   * @return {string}
   */
  mimeType() {
    return this._mimeType;
  }

  /**
   * @param {boolean} readOnly
   */
  setReadOnly(readOnly) {
    if (this._readOnly === readOnly) {
      return;
    }
    this.clearPositionHighlight();
    this._readOnly = readOnly;
    this.element.classList.toggle('CodeMirror-readonly', readOnly);
    this._codeMirror.setOption('readOnly', readOnly);
  }

  /**
   * @return {boolean}
   */
  readOnly() {
    return !!this._codeMirror.getOption('readOnly');
  }

  /**
   * @param {function(number):string} formatter
   */
  setLineNumberFormatter(formatter) {
    this._codeMirror.setOption('lineNumberFormatter', formatter);
  }

  /**
   * @override
   * @param {function(!KeyboardEvent)} handler
   */
  addKeyDownHandler(handler) {
    this._codeMirror.on('keydown', (CodeMirror, event) => handler(event));
  }

  /**
   * @param {number} lineNumber
   * @param {number} columnNumber
   * @param {!Element} element
   * @param {symbol} type
   * @param {boolean=} insertBefore
   * @return {!TextEditorBookMark}
   */
  addBookmark(lineNumber, columnNumber, element, type, insertBefore) {
    const bookmark = new TextEditorBookMark(
        this._codeMirror.setBookmark(
            new CodeMirror.Pos(lineNumber, columnNumber), {widget: element, insertLeft: insertBefore}),
        type, this);
    this._updateDecorations(lineNumber);
    return bookmark;
  }

  /**
   * @param {!TextUtils.TextRange} range
   * @param {symbol=} type
   * @return {!Array.<!TextEditorBookMark>}
   */
  bookmarks(range, type) {
    const pos = TextEditor.CodeMirrorUtils.toPos(range);
    let markers = this._codeMirror.findMarksAt(pos.start);
    if (!range.isEmpty()) {
      const middleMarkers = this._codeMirror.findMarks(pos.start, pos.end);
      const endMarkers = this._codeMirror.findMarksAt(pos.end);
      markers = markers.concat(middleMarkers, endMarkers);
    }
    const bookmarks = [];
    for (let i = 0; i < markers.length; i++) {
      const bookmark = markers[i][TextEditorBookMark._symbol];
      if (bookmark && (!type || bookmark.type() === type)) {
        bookmarks.push(bookmark);
      }
    }
    return bookmarks;
  }

  /**
   * @override
   */
  focus() {
    this._codeMirror.focus();
  }

  /**
   * @override
   * @return {boolean}
   */
  hasFocus() {
    return this._codeMirror.hasFocus();
  }

  /**
   * @param {function()} operation
   */
  operation(operation) {
    this._codeMirror.operation(operation);
  }

  /**
   * @param {number} lineNumber
   */
  scrollLineIntoView(lineNumber) {
    this._innerRevealLine(lineNumber, this._codeMirror.getScrollInfo());
  }

  /**
   * @param {number} lineNumber
   * @param {!{left: number, top: number, width: number, height: number, clientWidth: number, clientHeight: number}} scrollInfo
   */
  _innerRevealLine(lineNumber, scrollInfo) {
    const topLine = this._codeMirror.lineAtHeight(scrollInfo.top, 'local');
    const bottomLine = this._codeMirror.lineAtHeight(scrollInfo.top + scrollInfo.clientHeight, 'local');
    const linesPerScreen = bottomLine - topLine + 1;
    if (lineNumber < topLine) {
      const topLineToReveal = Math.max(lineNumber - (linesPerScreen / 2) + 1, 0) | 0;
      this._codeMirror.scrollIntoView(new CodeMirror.Pos(topLineToReveal, 0));
    } else if (lineNumber > bottomLine) {
      const bottomLineToReveal = Math.min(lineNumber + (linesPerScreen / 2) - 1, this.linesCount - 1) | 0;
      this._codeMirror.scrollIntoView(new CodeMirror.Pos(bottomLineToReveal, 0));
    }
  }

  /**
   * @param {!Element} element
   * @param {number} lineNumber
   * @param {number=} startColumn
   * @param {number=} endColumn
   */
  addDecoration(element, lineNumber, startColumn, endColumn) {
    const widget = this._codeMirror.addLineWidget(lineNumber, element);
    let update = null;
    if (typeof startColumn !== 'undefined') {
      if (typeof endColumn === 'undefined') {
        endColumn = Infinity;
      }
      update = this._updateFloatingDecoration.bind(this, element, lineNumber, startColumn, endColumn);
      update();
    }

    this._decorations.set(lineNumber, {element: element, update: update, widget: widget});
  }

  /**
   * @param {!Element} element
   * @param {number} lineNumber
   * @param {number} startColumn
   * @param {number} endColumn
   */
  _updateFloatingDecoration(element, lineNumber, startColumn, endColumn) {
    const base = this._codeMirror.cursorCoords(new CodeMirror.Pos(lineNumber, 0), 'page');
    const start = this._codeMirror.cursorCoords(new CodeMirror.Pos(lineNumber, startColumn), 'page');
    const end = this._codeMirror.charCoords(new CodeMirror.Pos(lineNumber, endColumn), 'page');
    element.style.width = (end.right - start.left) + 'px';
    element.style.left = (start.left - base.left) + 'px';
  }

  /**
   * @param {number} lineNumber
   */
  _updateDecorations(lineNumber) {
    this._decorations.get(lineNumber).forEach(innerUpdateDecorations);

    /**
     * @param {!TextEditor.CodeMirrorTextEditor.Decoration} decoration
     */
    function innerUpdateDecorations(decoration) {
      if (decoration.update) {
        decoration.update();
      }
    }
  }

  /**
   * @param {!Element} element
   * @param {number} lineNumber
   */
  removeDecoration(element, lineNumber) {
    this._decorations.get(lineNumber).forEach(innerRemoveDecoration.bind(this));

    /**
     * @this {CodeMirrorTextEditor}
     * @param {!TextEditor.CodeMirrorTextEditor.Decoration} decoration
     */
    function innerRemoveDecoration(decoration) {
      if (decoration.element !== element) {
        return;
      }
      this._codeMirror.removeLineWidget(decoration.widget);
      this._decorations.delete(lineNumber, decoration);
    }
  }

  /**
   * @param {number} lineNumber 0-based
   * @param {number=} columnNumber
   * @param {boolean=} shouldHighlight
   */
  revealPosition(lineNumber, columnNumber, shouldHighlight) {
    lineNumber = Number.constrain(lineNumber, 0, this._codeMirror.lineCount() - 1);
    if (typeof columnNumber !== 'number') {
      columnNumber = 0;
    }
    columnNumber = Number.constrain(columnNumber, 0, this._codeMirror.getLine(lineNumber).length);

    this.clearPositionHighlight();
    this._highlightedLine = this._codeMirror.getLineHandle(lineNumber);
    if (!this._highlightedLine) {
      return;
    }
    this.scrollLineIntoView(lineNumber);
    if (shouldHighlight) {
      this._codeMirror.addLineClass(
          this._highlightedLine, null, this._readOnly ? 'cm-readonly-highlight' : 'cm-highlight');
      if (!this._readOnly) {
        this._clearHighlightTimeout = setTimeout(this.clearPositionHighlight.bind(this), 2000);
      }
    }
    this.setSelection(TextUtils.TextRange.createFromLocation(lineNumber, columnNumber));
  }

  clearPositionHighlight() {
    if (this._clearHighlightTimeout) {
      clearTimeout(this._clearHighlightTimeout);
    }
    delete this._clearHighlightTimeout;

    if (this._highlightedLine) {
      this._codeMirror.removeLineClass(
          this._highlightedLine, null, this._readOnly ? 'cm-readonly-highlight' : 'cm-highlight');
    }
    delete this._highlightedLine;
  }

  /**
   * @override
   * @return {!Array.<!Element>}
   */
  elementsToRestoreScrollPositionsFor() {
    return [];
  }

  /**
   * @param {number} width
   * @param {number} height
   */
  _updatePaddingBottom(width, height) {
    if (!this._options.padBottom) {
      return;
    }
    const scrollInfo = this._codeMirror.getScrollInfo();
    let newPaddingBottom;
    const linesElement = this._codeMirrorElement.querySelector('.CodeMirror-lines');
    const lineCount = this._codeMirror.lineCount();
    if (lineCount <= 1) {
      newPaddingBottom = 0;
    } else {
      newPaddingBottom =
          Math.max(scrollInfo.clientHeight - this._codeMirror.getLineHandle(this._codeMirror.lastLine()).height, 0);
    }
    newPaddingBottom += 'px';
    linesElement.style.paddingBottom = newPaddingBottom;
    this._codeMirror.setSize(width, height);
  }

  _resizeEditor() {
    const parentElement = this.element.parentElement;
    if (!parentElement || !this.isShowing()) {
      return;
    }
    this._codeMirror.operation(() => {
      const scrollLeft = this._codeMirror.doc.scrollLeft;
      const scrollTop = this._codeMirror.doc.scrollTop;
      const width = parentElement.offsetWidth;
      const height = parentElement.offsetHeight - this.element.offsetTop;
      if (this._options.autoHeight) {
        this._codeMirror.setSize(width, 'auto');
      } else {
        this._codeMirror.setSize(width, height);
        this._updatePaddingBottom(width, height);
      }
      this._codeMirror.scrollTo(scrollLeft, scrollTop);
    });
  }

  /**
   * @override
   */
  onResize() {
    if (this._autocompleteController) {
      this._autocompleteController.clearAutocomplete();
    }
    this._resizeEditor();
    this._editorSizeInSync = true;
    if (this._selectionSetScheduled) {
      delete this._selectionSetScheduled;
      this.setSelection(this._lastSelection);
    }
  }

  /**
   * @param {!TextUtils.TextRange} range
   * @param {string} text
   * @param {string=} origin
   * @return {!TextUtils.TextRange}
   */
  editRange(range, text, origin) {
    const pos = TextEditor.CodeMirrorUtils.toPos(range);
    this._codeMirror.replaceRange(text, pos.start, pos.end, origin);
    const newRange = TextEditor.CodeMirrorUtils.toRange(
        pos.start, this._codeMirror.posFromIndex(this._codeMirror.indexFromPos(pos.start) + text.length));
    this.dispatchEventToListeners(UI.TextEditor.Events.TextChanged, {oldRange: range, newRange: newRange});
    return newRange;
  }

  /**
   * @override
   */
  clearAutocomplete() {
    if (this._autocompleteController) {
      this._autocompleteController.clearAutocomplete();
    }
  }

  /**
   * @param {number} lineNumber
   * @param {number} column
   * @param {function(string):boolean} isWordChar
   * @return {!TextUtils.TextRange}
   */
  wordRangeForCursorPosition(lineNumber, column, isWordChar) {
    const line = this.line(lineNumber);
    let wordStart = column;
    if (column !== 0 && isWordChar(line.charAt(column - 1))) {
      wordStart = column - 1;
      while (wordStart > 0 && isWordChar(line.charAt(wordStart - 1))) {
        --wordStart;
      }
    }
    let wordEnd = column;
    while (wordEnd < line.length && isWordChar(line.charAt(wordEnd))) {
      ++wordEnd;
    }
    return new TextUtils.TextRange(lineNumber, wordStart, lineNumber, wordEnd);
  }

  /**
   * @param {!CodeMirror} codeMirror
   * @param {!Array.<!CodeMirror.ChangeObject>} changes
   */
  _changes(codeMirror, changes) {
    if (!changes.length) {
      return;
    }

    this._updatePlaceholder();

    // We do not show "scroll beyond end of file" span for one line documents, so we need to check if "document has one line" changed.
    const hasOneLine = this._codeMirror.lineCount() === 1;
    if (hasOneLine !== this._hasOneLine) {
      this._resizeEditor();
    }
    this._hasOneLine = hasOneLine;

    this._decorations.valuesArray().forEach(decoration => this._codeMirror.removeLineWidget(decoration.widget));
    this._decorations.clear();

    const edits = [];
    let currentEdit;

    for (let changeIndex = 0; changeIndex < changes.length; ++changeIndex) {
      const changeObject = changes[changeIndex];
      const edit = TextEditor.CodeMirrorUtils.changeObjectToEditOperation(changeObject);
      if (currentEdit && edit.oldRange.equal(currentEdit.newRange)) {
        currentEdit.newRange = edit.newRange;
      } else {
        currentEdit = edit;
        edits.push(currentEdit);
      }
    }

    for (let i = 0; i < edits.length; i++) {
      this.dispatchEventToListeners(
          UI.TextEditor.Events.TextChanged, {oldRange: edits[i].oldRange, newRange: edits[i].newRange});
    }
  }

  /**
   * @param {!CodeMirror} codeMirror
   * @param {{ranges: !Array.<{head: !CodeMirror.Pos, anchor: !CodeMirror.Pos}>}} selection
   */
  _beforeSelectionChange(codeMirror, selection) {
    this._selectNextOccurrenceController.selectionWillChange();
  }

  /**
   * @param {number} lineNumber
   */
  scrollToLine(lineNumber) {
    const pos = new CodeMirror.Pos(lineNumber, 0);
    const coords = this._codeMirror.charCoords(pos, 'local');
    this._codeMirror.scrollTo(0, coords.top);
  }

  /**
   * @return {number}
   */
  firstVisibleLine() {
    return this._codeMirror.lineAtHeight(this._codeMirror.getScrollInfo().top, 'local');
  }

  /**
   * @return {number}
   */
  scrollTop() {
    return this._codeMirror.getScrollInfo().top;
  }

  /**
   * @param {number} scrollTop
   */
  setScrollTop(scrollTop) {
    this._codeMirror.scrollTo(0, scrollTop);
  }

  /**
   * @return {number}
   */
  lastVisibleLine() {
    const scrollInfo = this._codeMirror.getScrollInfo();
    return this._codeMirror.lineAtHeight(scrollInfo.top + scrollInfo.clientHeight, 'local');
  }

  /**
   * @override
   * @return {!TextUtils.TextRange}
   */
  selection() {
    const start = this._codeMirror.getCursor('anchor');
    const end = this._codeMirror.getCursor('head');

    return TextEditor.CodeMirrorUtils.toRange(start, end);
  }

  /**
   * @return {!Array.<!TextUtils.TextRange>}
   */
  selections() {
    const selectionList = this._codeMirror.listSelections();
    const result = [];
    for (let i = 0; i < selectionList.length; ++i) {
      const selection = selectionList[i];
      result.push(TextEditor.CodeMirrorUtils.toRange(selection.anchor, selection.head));
    }
    return result;
  }

  /**
   * @return {?TextUtils.TextRange}
   */
  lastSelection() {
    return this._lastSelection;
  }

  /**
   * @override
   * @param {!TextUtils.TextRange} textRange
   * @param {boolean=} dontScroll
   */
  setSelection(textRange, dontScroll) {
    this._lastSelection = textRange;
    if (!this._editorSizeInSync) {
      this._selectionSetScheduled = true;
      return;
    }
    const pos = TextEditor.CodeMirrorUtils.toPos(textRange);
    this._codeMirror.setSelection(pos.start, pos.end, {scroll: !dontScroll});
  }

  /**
   * @param {!Array.<!TextUtils.TextRange>} ranges
   * @param {number=} primarySelectionIndex
   */
  setSelections(ranges, primarySelectionIndex) {
    const selections = [];
    for (let i = 0; i < ranges.length; ++i) {
      const selection = TextEditor.CodeMirrorUtils.toPos(ranges[i]);
      selections.push({anchor: selection.start, head: selection.end});
    }
    primarySelectionIndex = primarySelectionIndex || 0;
    this._codeMirror.setSelections(selections, primarySelectionIndex, {scroll: false});
  }

  /**
   * @param {string} text
   */
  _detectLineSeparator(text) {
    this._lineSeparator = text.indexOf('\r\n') >= 0 ? '\r\n' : '\n';
  }

  /**
   * @override
   * @param {string} text
   */
  setText(text) {
    if (text.length > CodeMirrorTextEditor.MaxEditableTextSize) {
      this.configureAutocomplete(null);
      this.setReadOnly(true);
    }
    this._codeMirror.setValue(text);
    if (this._shouldClearHistory) {
      this._codeMirror.clearHistory();
      this._shouldClearHistory = false;
    }
    this._detectLineSeparator(text);

    if (this._hasLongLines()) {
      this._enableLongLinesMode();
    } else {
      this._disableLongLinesMode();
    }

    if (!this.isShowing()) {
      this.refresh();
    }
  }

  /**
   * @override
   * @param {!TextUtils.TextRange=} textRange
   * @return {string}
   */
  text(textRange) {
    if (!textRange) {
      return this._codeMirror.getValue(this._lineSeparator);
    }
    const pos = TextEditor.CodeMirrorUtils.toPos(textRange.normalize());
    return this._codeMirror.getRange(pos.start, pos.end, this._lineSeparator);
  }

  /**
   * @override
   * @return {string}
   */
  textWithCurrentSuggestion() {
    if (!this._autocompleteController) {
      return this.text();
    }
    return this._autocompleteController.textWithCurrentSuggestion();
  }

  /**
   * @override
   * @return {!TextUtils.TextRange}
   */
  fullRange() {
    const lineCount = this.linesCount;
    const lastLine = this._codeMirror.getLine(lineCount - 1);
    return TextEditor.CodeMirrorUtils.toRange(
        new CodeMirror.Pos(0, 0), new CodeMirror.Pos(lineCount - 1, lastLine.length));
  }

  /**
   * @return {number}
   */
  currentLineNumber() {
    return this._codeMirror.getCursor().line;
  }

  /**
   * @override
   * @param {number} lineNumber
   * @return {string}
   */
  line(lineNumber) {
    return this._codeMirror.getLine(lineNumber);
  }

  /**
   * @return {number}
   */
  get linesCount() {
    return this._codeMirror.lineCount();
  }

  /**
   * @override
   */
  newlineAndIndent() {
    this._codeMirror.execCommand('newlineAndIndent');
  }

  /**
   * @param {number} lineNumber
   * @param {number} columnNumber
   * @return {!TextEditorPositionHandle}
   */
  textEditorPositionHandle(lineNumber, columnNumber) {
    return new CodeMirrorPositionHandle(this._codeMirror, new CodeMirror.Pos(lineNumber, columnNumber));
  }

  _updatePlaceholder() {
    if (!this._placeholderElement) {
      return;
    }

    this._placeholderElement.remove();

    if (this.linesCount === 1 && !this.line(0)) {
      this._codeMirror.display.lineSpace.insertBefore(
          this._placeholderElement, this._codeMirror.display.lineSpace.firstChild);
    }
  }
}

CodeMirrorTextEditor.maxHighlightLength = 1000;
CodeMirrorTextEditor.LongLineModeLineLengthThreshold = 2000;
CodeMirrorTextEditor.MaxEditableTextSize = 1024 * 1024 * 10;

CodeMirrorTextEditor._overrideModeWithPrefixedTokens('css', 'css-');
CodeMirrorTextEditor._overrideModeWithPrefixedTokens('javascript', 'js-');
CodeMirrorTextEditor._overrideModeWithPrefixedTokens('xml', 'xml-');

CodeMirror.commands.autocomplete = CodeMirrorTextEditor.autocompleteCommand;
CodeMirror.commands.undoLastSelection = CodeMirrorTextEditor.undoLastSelectionCommand;
CodeMirror.commands.selectNextOccurrence = CodeMirrorTextEditor.selectNextOccurrenceCommand;
CodeMirror.commands.moveCamelLeft = CodeMirrorTextEditor.moveCamelLeftCommand.bind(null, false);
CodeMirror.commands.selectCamelLeft = CodeMirrorTextEditor.moveCamelLeftCommand.bind(null, true);
CodeMirror.commands.moveCamelRight = CodeMirrorTextEditor.moveCamelRightCommand.bind(null, false);
CodeMirror.commands.selectCamelRight = CodeMirrorTextEditor.moveCamelRightCommand.bind(null, true);

/**
 * @param {!CodeMirror} codeMirror
 */
CodeMirror.commands.UserIndent = function(codeMirror) {
  const ranges = codeMirror.listSelections();
  if (ranges.length === 0) {
    return;
  }

  if (codeMirror.somethingSelected()) {
    codeMirror.indentSelection('add');
    return;
  }

  const indentation = Common.moduleSetting('textEditorIndent').get();
  codeMirror.replaceSelection(indentation);
};

/**
 * @param {!CodeMirror} codeMirror
 * @return {!Object|undefined}
 */
CodeMirror.commands.indentLessOrPass = function(codeMirror) {
  const selections = codeMirror.listSelections();
  if (selections.length === 1) {
    const range = TextEditor.CodeMirrorUtils.toRange(selections[0].anchor, selections[0].head);
    if (range.isEmpty() && !/^\s/.test(codeMirror.getLine(range.startLine))) {
      return CodeMirror.Pass;
    }
  }
  codeMirror.execCommand('indentLess');
};

/**
 * @param {!CodeMirror} codeMirror
 */
CodeMirror.commands.gotoMatchingBracket = function(codeMirror) {
  const updatedSelections = [];
  const selections = codeMirror.listSelections();
  for (let i = 0; i < selections.length; ++i) {
    const selection = selections[i];
    const cursor = selection.head;
    const matchingBracket = codeMirror.findMatchingBracket(cursor, false, {maxScanLines: 10000});
    let updatedHead = cursor;
    if (matchingBracket && matchingBracket.match) {
      const columnCorrection = CodeMirror.cmpPos(matchingBracket.from, cursor) === 0 ? 1 : 0;
      updatedHead = new CodeMirror.Pos(matchingBracket.to.line, matchingBracket.to.ch + columnCorrection);
    }
    updatedSelections.push({anchor: updatedHead, head: updatedHead});
  }
  codeMirror.setSelections(updatedSelections);
};

/**
 * @param {!CodeMirror} codemirror
 */
CodeMirror.commands.undoAndReveal = function(codemirror) {
  const scrollInfo = codemirror.getScrollInfo();
  codemirror.execCommand('undo');
  const cursor = codemirror.getCursor('start');
  codemirror._codeMirrorTextEditor._innerRevealLine(cursor.line, scrollInfo);
  const autocompleteController = codemirror._codeMirrorTextEditor._autocompleteController;
  if (autocompleteController) {
    autocompleteController.clearAutocomplete();
  }
};

/**
 * @param {!CodeMirror} codemirror
 */
CodeMirror.commands.redoAndReveal = function(codemirror) {
  const scrollInfo = codemirror.getScrollInfo();
  codemirror.execCommand('redo');
  const cursor = codemirror.getCursor('start');
  codemirror._codeMirrorTextEditor._innerRevealLine(cursor.line, scrollInfo);
  const autocompleteController = codemirror._codeMirrorTextEditor._autocompleteController;
  if (autocompleteController) {
    autocompleteController.clearAutocomplete();
  }
};

/**
 * @param {!CodeMirror} codemirror
 * @return {!Object|undefined}
 */
CodeMirror.commands.dismiss = function(codemirror) {
  const selections = codemirror.listSelections();
  const selection = selections[0];
  if (selections.length === 1) {
    if (TextEditor.CodeMirrorUtils.toRange(selection.anchor, selection.head).isEmpty()) {
      return CodeMirror.Pass;
    }
    codemirror.setSelection(selection.anchor, selection.anchor, {scroll: false});
    codemirror._codeMirrorTextEditor.scrollLineIntoView(selection.anchor.line);
    return;
  }

  codemirror.setSelection(selection.anchor, selection.head, {scroll: false});
  codemirror._codeMirrorTextEditor.scrollLineIntoView(selection.anchor.line);
};

/**
 * @param {!CodeMirror} codemirror
 * @return {!Object|undefined}
 */
CodeMirror.commands.goSmartPageUp = function(codemirror) {
  if (codemirror._codeMirrorTextEditor.selection().equal(TextUtils.TextRange.createFromLocation(0, 0))) {
    return CodeMirror.Pass;
  }
  codemirror.execCommand('goPageUp');
};

/**
 * @param {!CodeMirror} codemirror
 * @return {!Object|undefined}
 */
CodeMirror.commands.goSmartPageDown = function(codemirror) {
  if (codemirror._codeMirrorTextEditor.selection().equal(
          codemirror._codeMirrorTextEditor.fullRange().collapseToEnd())) {
    return CodeMirror.Pass;
  }
  codemirror.execCommand('goPageDown');
};

/**
 * @implements {TextEditorPositionHandle}
 * @unrestricted
 */
export class CodeMirrorPositionHandle {
  /**
   * @param {!CodeMirror} codeMirror
   * @param {!CodeMirror.Pos} pos
   */
  constructor(codeMirror, pos) {
    this._codeMirror = codeMirror;
    this._lineHandle = codeMirror.getLineHandle(pos.line);
    this._columnNumber = pos.ch;
  }

  /**
   * @override
   * @return {?{lineNumber: number, columnNumber: number}}
   */
  resolve() {
    const lineNumber = this._lineHandle ? this._codeMirror.getLineNumber(this._lineHandle) : null;
    if (typeof lineNumber !== 'number') {
      return null;
    }
    return {lineNumber: lineNumber, columnNumber: this._columnNumber};
  }

  /**
   * @override
   * @param {!TextEditorPositionHandle} argPositionHandle
   * @return {boolean}
   */
  equal(argPositionHandle) {
    const positionHandle = /** @type {!CodeMirrorPositionHandle} */ (argPositionHandle);
    return positionHandle._lineHandle === this._lineHandle && positionHandle._columnNumber === this._columnNumber &&
        positionHandle._codeMirror === this._codeMirror;
  }
}

/**
 * @unrestricted
 */
export class SelectNextOccurrenceController {
  /**
   * @param {!CodeMirrorTextEditor} textEditor
   * @param {!CodeMirror} codeMirror
   */
  constructor(textEditor, codeMirror) {
    this._textEditor = textEditor;
    this._codeMirror = codeMirror;
  }

  selectionWillChange() {
    if (!this._muteSelectionListener) {
      delete this._fullWordSelection;
    }
  }

  /**
   * @param {!Array.<!TextUtils.TextRange>} selections
   * @param {!TextUtils.TextRange} range
   * @return {boolean}
   */
  _findRange(selections, range) {
    for (let i = 0; i < selections.length; ++i) {
      if (range.equal(selections[i])) {
        return true;
      }
    }
    return false;
  }

  undoLastSelection() {
    this._muteSelectionListener = true;
    this._codeMirror.execCommand('undoSelection');
    this._muteSelectionListener = false;
  }

  selectNextOccurrence() {
    const selections = this._textEditor.selections();
    let anyEmptySelection = false;
    for (let i = 0; i < selections.length; ++i) {
      const selection = selections[i];
      anyEmptySelection = anyEmptySelection || selection.isEmpty();
      if (selection.startLine !== selection.endLine) {
        return;
      }
    }
    if (anyEmptySelection) {
      this._expandSelectionsToWords(selections);
      return;
    }

    const last = selections[selections.length - 1];
    let next = last;
    do {
      next = this._findNextOccurrence(next, !!this._fullWordSelection);
    } while (next && this._findRange(selections, next) && !next.equal(last));

    if (!next) {
      return;
    }
    selections.push(next);

    this._muteSelectionListener = true;
    this._textEditor.setSelections(selections, selections.length - 1);
    delete this._muteSelectionListener;

    this._textEditor.scrollLineIntoView(next.startLine);
  }

  /**
   * @param {!Array.<!TextUtils.TextRange>} selections
   */
  _expandSelectionsToWords(selections) {
    const newSelections = [];
    for (let i = 0; i < selections.length; ++i) {
      const selection = selections[i];
      const startRangeWord = this._textEditor.wordRangeForCursorPosition(
                                 selection.startLine, selection.startColumn, TextUtils.TextUtils.isWordChar) ||
          TextUtils.TextRange.createFromLocation(selection.startLine, selection.startColumn);
      const endRangeWord = this._textEditor.wordRangeForCursorPosition(
                               selection.endLine, selection.endColumn, TextUtils.TextUtils.isWordChar) ||
          TextUtils.TextRange.createFromLocation(selection.endLine, selection.endColumn);
      const newSelection = new TextUtils.TextRange(
          startRangeWord.startLine, startRangeWord.startColumn, endRangeWord.endLine, endRangeWord.endColumn);
      newSelections.push(newSelection);
    }
    this._textEditor.setSelections(newSelections, newSelections.length - 1);
    this._fullWordSelection = true;
  }

  /**
   * @param {!TextUtils.TextRange} range
   * @param {boolean} fullWord
   * @return {?TextUtils.TextRange}
   */
  _findNextOccurrence(range, fullWord) {
    range = range.normalize();
    let matchedLineNumber;
    let matchedColumnNumber;
    const textToFind = this._textEditor.text(range);
    function findWordInLine(wordRegex, lineNumber, lineText, from, to) {
      if (typeof matchedLineNumber === 'number') {
        return true;
      }
      wordRegex.lastIndex = from;
      const result = wordRegex.exec(lineText);
      if (!result || result.index + textToFind.length > to) {
        return false;
      }
      matchedLineNumber = lineNumber;
      matchedColumnNumber = result.index;
      return true;
    }

    let iteratedLineNumber;
    function lineIterator(regex, lineHandle) {
      if (findWordInLine(regex, iteratedLineNumber++, lineHandle.text, 0, lineHandle.text.length)) {
        return true;
      }
    }

    let regexSource = textToFind.escapeForRegExp();
    if (fullWord) {
      regexSource = '\\b' + regexSource + '\\b';
    }
    const wordRegex = new RegExp(regexSource, 'g');
    const currentLineText = this._codeMirror.getLine(range.startLine);

    findWordInLine(wordRegex, range.startLine, currentLineText, range.endColumn, currentLineText.length);
    iteratedLineNumber = range.startLine + 1;
    this._codeMirror.eachLine(range.startLine + 1, this._codeMirror.lineCount(), lineIterator.bind(null, wordRegex));
    iteratedLineNumber = 0;
    this._codeMirror.eachLine(0, range.startLine, lineIterator.bind(null, wordRegex));
    findWordInLine(wordRegex, range.startLine, currentLineText, 0, range.startColumn);

    if (typeof matchedLineNumber !== 'number') {
      return null;
    }
    return new TextUtils.TextRange(
        matchedLineNumber, matchedColumnNumber, matchedLineNumber, matchedColumnNumber + textToFind.length);
  }
}


/**
 * @interface
 */
export class TextEditorPositionHandle {
  /**
   * @return {?{lineNumber: number, columnNumber: number}}
   */
  resolve() {
  }

  /**
   * @param {!TextEditorPositionHandle} positionHandle
   * @return {boolean}
   */
  equal(positionHandle) {}
}

/** @type {!Set<!Root.Runtime.Extension>} */
export const _loadedMimeModeExtensions = new Set();


/**
 * @interface
 */
export class CodeMirrorMimeMode {
  /**
   * @param {!Root.Runtime.Extension} extension
   */
  async install(extension) {
  }
}

/**
 * @unrestricted
 */
export class TextEditorBookMark {
  /**
   * @param {!CodeMirror.TextMarker} marker
   * @param {symbol} type
   * @param {!CodeMirrorTextEditor} editor
   */
  constructor(marker, type, editor) {
    marker[TextEditorBookMark._symbol] = this;

    this._marker = marker;
    this._type = type;
    this._editor = editor;
  }

  clear() {
    const position = this._marker.find();
    this._marker.clear();
    if (position) {
      this._editor._updateDecorations(position.line);
    }
  }

  refresh() {
    this._marker.changed();
    const position = this._marker.find();
    if (position) {
      this._editor._updateDecorations(position.line);
    }
  }

  /**
   * @return {symbol}
   */
  type() {
    return this._type;
  }

  /**
   * @return {?TextUtils.TextRange}
   */
  position() {
    const pos = this._marker.find();
    return pos ? TextUtils.TextRange.createFromLocation(pos.line, pos.ch) : null;
  }
}

TextEditorBookMark._symbol = Symbol('TextEditorBookMark');

/**
 * @implements {UI.TextEditorFactory}
 * @unrestricted
 */
export class CodeMirrorTextEditorFactory {
  /**
   * @override
   * @param {!UI.TextEditor.Options} options
   * @return {!CodeMirrorTextEditor}
   */
  createEditor(options) {
    return new CodeMirrorTextEditor(options);
  }
}

// CodeMirror uses an offscreen <textarea> to detect input. Due to inconsistencies in the many browsers it supports,
// it simplifies things by regularly checking if something is in the textarea, adding those characters to the document,
// and then clearing the textarea. This breaks assistive technology that wants to read from CodeMirror, because the
// <textarea> that they interact with is constantly empty.
// Because we target up-to-date Chrome, we can guarantee consistent input events. This lets us leave the current
// line from the editor in our <textarea>. CodeMirror still expects a mostly empty <textarea>, so we pass CodeMirror a
// fake <textarea> that only contains the users input.
CodeMirror.inputStyles.devToolsAccessibleTextArea = class extends CodeMirror.inputStyles.textarea {
  /**
   * @override
   * @param {!Object} display
   */
  init(display) {
    super.init(display);
    UI.ARIAUtils.setAccessibleName(this.textarea, this.cm.options.devtoolsAccessibleName || ls`Code editor`);
    this.textarea.addEventListener('compositionstart', this._onCompositionStart.bind(this));
  }

  _onCompositionStart() {
    if (this.textarea.selectionEnd === this.textarea.value.length) {
      return;
    }
    // CodeMirror always expects the caret to be at the end of the textarea
    // When in IME composition mode, clip the textarea to how CodeMirror expects it,
    // and then let CodeMirror do it's thing.
    this.textarea.value = this.textarea.value.substring(0, this.textarea.selectionEnd);
    this.textarea.setSelectionRange(this.textarea.value.length, this.textarea.value.length);
    this.prevInput = this.textarea.value;
  }

  /**
   * @override
   * @param {boolean=} typing
   */
  reset(typing) {
    if (typing || this.contextMenuPending || this.composing || this.cm.somethingSelected()) {
      super.reset(typing);
      return;
    }

    // When navigating around the document, keep the current visual line in the textarea.
    const cursor = this.cm.getCursor();
    let start, end;
    if (this.cm.options.lineWrapping) {
      // To get the visual line, compute the leftmost and rightmost character positions.
      const top = this.cm.charCoords(cursor, 'page').top;
      start = this.cm.coordsChar({left: -Infinity, top});
      end = this.cm.coordsChar({left: Infinity, top});
    } else {
      // Limit the line to 1000 characters to prevent lag.
      const offset = Math.floor(cursor.ch / 1000) * 1000;
      start = {ch: offset, line: cursor.line};
      end = {ch: offset + 1000, line: cursor.line};
    }
    this.textarea.value = this.cm.getRange(start, end);
    const caretPosition = cursor.ch - start.ch;
    this.textarea.setSelectionRange(caretPosition, caretPosition);
    this.prevInput = this.textarea.value;
  }

  /**
   * @override
   * @return {boolean}
   */
  poll() {
    if (this.contextMenuPending || this.composing) {
      return super.poll();
    }
    const text = this.textarea.value;
    let start = 0;
    const length = Math.min(this.prevInput.length, text.length);
    while (start < length && this.prevInput[start] === text[start]) {
      ++start;
    }
    let end = 0;
    while (end < length - start && this.prevInput[this.prevInput.length - end - 1] === text[text.length - end - 1]) {
      ++end;
    }

    // CodeMirror expects the user to be typing into a blank <textarea>.
    // Pass a fake textarea into super.poll that only contains the users input.
    /** @type {!HTMLTextAreaElement} */
    const placeholder = this.textarea;
    this.textarea = /** @type {!HTMLTextAreaElement} */ (createElement('textarea'));
    this.textarea.value = text.substring(start, text.length - end);
    this.textarea.setSelectionRange(placeholder.selectionStart - start, placeholder.selectionEnd - start);
    this.prevInput = '';
    const result = super.poll();
    this.prevInput = text;
    this.textarea = placeholder;
    return result;
  }
};

/* Legacy exported object */
self.TextEditor = self.TextEditor || {};

/* Legacy exported object */
TextEditor = TextEditor || {};

/** @constructor */
TextEditor.CodeMirrorTextEditor = CodeMirrorTextEditor;

/** @constructor */
TextEditor.CodeMirrorTextEditor.SelectNextOccurrenceController = SelectNextOccurrenceController;

/** @interface */
TextEditor.TextEditorPositionHandle = TextEditorPositionHandle;

TextEditor.CodeMirrorTextEditor._loadedMimeModeExtensions = _loadedMimeModeExtensions;

/** @constructor */
TextEditor.CodeMirrorPositionHandle = CodeMirrorPositionHandle;

/** @interface */
TextEditor.CodeMirrorMimeMode = CodeMirrorMimeMode;

/** @constructor */
TextEditor.TextEditorBookMark = TextEditorBookMark;

/** @constructor */
TextEditor.CodeMirrorTextEditorFactory = CodeMirrorTextEditorFactory;

/**
 * @typedef {{
  *  element: !Element,
  *  widget: !CodeMirror.LineWidget,
  *  update: ?function()
  * }}
  */
TextEditor.CodeMirrorTextEditor.Decoration;
