// Copyright (c) 2014 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.

/**
 * @implements {UI.SuggestBoxDelegate}
 * @unrestricted
 */
export class TextEditorAutocompleteController {
  /**
   * @param {!TextEditor.CodeMirrorTextEditor} textEditor
   * @param {!CodeMirror} codeMirror
   * @param {!UI.AutocompleteConfig} config
   */
  constructor(textEditor, codeMirror, config) {
    this._textEditor = textEditor;
    this._codeMirror = codeMirror;
    this._config = config;
    this._initialized = false;

    this._onScroll = this._onScroll.bind(this);
    this._onCursorActivity = this._onCursorActivity.bind(this);
    this._changes = this._changes.bind(this);
    this._blur = this._blur.bind(this);
    this._beforeChange = this._beforeChange.bind(this);
    this._mouseDown = () => {
      this.clearAutocomplete();
      this._tooltipGlassPane.hide();
    };
    this._codeMirror.on('changes', this._changes);
    this._lastHintText = '';
    /** @type {?UI.SuggestBox} */
    this._suggestBox = null;
    /** @type {?UI.SuggestBox.Suggestion} */
    this._currentSuggestion = null;
    this._hintElement = createElementWithClass('span', 'auto-complete-text');

    this._tooltipGlassPane = new UI.GlassPane();
    this._tooltipGlassPane.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent);
    this._tooltipGlassPane.setOutsideClickCallback(this._tooltipGlassPane.hide.bind(this._tooltipGlassPane));
    this._tooltipElement = createElementWithClass('div', 'autocomplete-tooltip');
    const shadowRoot =
        UI.createShadowRootWithCoreStyles(this._tooltipGlassPane.contentElement, 'text_editor/autocompleteTooltip.css');
    shadowRoot.appendChild(this._tooltipElement);
  }

  _initializeIfNeeded() {
    if (this._initialized) {
      return;
    }
    this._initialized = true;
    this._codeMirror.on('scroll', this._onScroll);
    this._codeMirror.on('cursorActivity', this._onCursorActivity);
    this._codeMirror.on('mousedown', this._mouseDown);
    this._codeMirror.on('blur', this._blur);
    if (this._config.isWordChar) {
      this._codeMirror.on('beforeChange', this._beforeChange);
      this._dictionary = new Common.TextDictionary();
      this._addWordsFromText(this._codeMirror.getValue());
    }
  }

  dispose() {
    this._codeMirror.off('changes', this._changes);
    if (this._initialized) {
      this._codeMirror.off('scroll', this._onScroll);
      this._codeMirror.off('cursorActivity', this._onCursorActivity);
      this._codeMirror.off('mousedown', this._mouseDown);
      this._codeMirror.off('blur', this._blur);
    }
    if (this._dictionary) {
      this._codeMirror.off('beforeChange', this._beforeChange);
      this._dictionary.reset();
    }
  }

  /**
   * @param {!CodeMirror} codeMirror
   * @param {!CodeMirror.BeforeChangeObject} changeObject
   */
  _beforeChange(codeMirror, changeObject) {
    this._updatedLines = this._updatedLines || {};
    for (let i = changeObject.from.line; i <= changeObject.to.line; ++i) {
      if (this._updatedLines[i] === undefined) {
        this._updatedLines[i] = this._codeMirror.getLine(i);
      }
    }
  }

  /**
   * @param {string} text
   */
  _addWordsFromText(text) {
    TextUtils.TextUtils.textToWords(
        text, /** @type {function(string):boolean} */ (this._config.isWordChar), addWord.bind(this));

    /**
     * @param {string} word
     * @this {TextEditorAutocompleteController}
     */
    function addWord(word) {
      if (word.length && (word[0] < '0' || word[0] > '9')) {
        this._dictionary.addWord(word);
      }
    }
  }

  /**
   * @param {string} text
   */
  _removeWordsFromText(text) {
    TextUtils.TextUtils.textToWords(
        text, /** @type {function(string):boolean} */ (this._config.isWordChar),
        word => this._dictionary.removeWord(word));
  }

  /**
   * @param {number} lineNumber
   * @param {number} columnNumber
   * @return {?TextUtils.TextRange}
   */
  _substituteRange(lineNumber, columnNumber) {
    let range =
        this._config.substituteRangeCallback ? this._config.substituteRangeCallback(lineNumber, columnNumber) : null;
    if (!range && this._config.isWordChar) {
      range = this._textEditor.wordRangeForCursorPosition(lineNumber, columnNumber, this._config.isWordChar);
    }
    return range;
  }

  /**
   * @param {!TextUtils.TextRange} queryRange
   * @param {!TextUtils.TextRange} substituteRange
   * @param {boolean=} force
   * @return {!Promise.<!UI.SuggestBox.Suggestions>}
   */
  _wordsWithQuery(queryRange, substituteRange, force) {
    const external =
        this._config.suggestionsCallback ? this._config.suggestionsCallback(queryRange, substituteRange, force) : null;
    if (external) {
      return external;
    }

    if (!this._dictionary || (!force && queryRange.isEmpty())) {
      return Promise.resolve([]);
    }

    let completions = this._dictionary.wordsWithPrefix(this._textEditor.text(queryRange));
    const substituteWord = this._textEditor.text(substituteRange);
    if (this._dictionary.wordCount(substituteWord) === 1) {
      completions = completions.filter(word => word !== substituteWord);
    }

    completions.sort((a, b) => this._dictionary.wordCount(b) - this._dictionary.wordCount(a) || a.length - b.length);
    return Promise.resolve(completions.map(item => ({text: item})));
  }

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

    if (this._dictionary && this._updatedLines) {
      for (const lineNumber in this._updatedLines) {
        this._removeWordsFromText(this._updatedLines[lineNumber]);
      }
      delete this._updatedLines;

      const linesToUpdate = {};
      for (let changeIndex = 0; changeIndex < changes.length; ++changeIndex) {
        const changeObject = changes[changeIndex];
        const editInfo = TextEditor.CodeMirrorUtils.changeObjectToEditOperation(changeObject);
        for (let i = editInfo.newRange.startLine; i <= editInfo.newRange.endLine; ++i) {
          linesToUpdate[i] = this._codeMirror.getLine(i);
        }
      }
      for (const lineNumber in linesToUpdate) {
        this._addWordsFromText(linesToUpdate[lineNumber]);
      }
    }

    let singleCharInput = false;
    let singleCharDelete = false;
    const cursor = this._codeMirror.getCursor('head');
    for (let changeIndex = 0; changeIndex < changes.length; ++changeIndex) {
      const changeObject = changes[changeIndex];
      if (changeObject.origin === '+input' && changeObject.text.length === 1 && changeObject.text[0].length === 1 &&
          changeObject.to.line === cursor.line && changeObject.to.ch + 1 === cursor.ch) {
        singleCharInput = true;
        break;
      }
      if (changeObject.origin === '+delete' && changeObject.removed.length === 1 &&
          changeObject.removed[0].length === 1 && changeObject.to.line === cursor.line &&
          changeObject.to.ch - 1 === cursor.ch) {
        singleCharDelete = true;
        break;
      }
    }
    if (this._queryRange) {
      if (singleCharInput) {
        this._queryRange.endColumn++;
      } else if (singleCharDelete) {
        this._queryRange.endColumn--;
      }
      if (singleCharDelete || singleCharInput) {
        this._setHint(this._lastHintText);
      }
    }

    if (singleCharInput || singleCharDelete) {
      setImmediate(this.autocomplete.bind(this));
    } else {
      this.clearAutocomplete();
    }
  }

  _blur() {
    this.clearAutocomplete();
  }

  /**
   * @param {!TextUtils.TextRange} mainSelection
   * @return {boolean}
   */
  _validateSelectionsContexts(mainSelection) {
    const selections = this._codeMirror.listSelections();
    if (selections.length <= 1) {
      return true;
    }
    const mainSelectionContext = this._textEditor.text(mainSelection);
    for (let i = 0; i < selections.length; ++i) {
      const wordRange = this._substituteRange(selections[i].head.line, selections[i].head.ch);
      if (!wordRange) {
        return false;
      }
      const context = this._textEditor.text(wordRange);
      if (context !== mainSelectionContext) {
        return false;
      }
    }
    return true;
  }

  /**
   * @param {boolean=} force
   */
  autocomplete(force) {
    this._initializeIfNeeded();
    if (this._codeMirror.somethingSelected()) {
      this._hideSuggestBox();
      return;
    }

    const cursor = this._codeMirror.getCursor('head');
    const substituteRange = this._substituteRange(cursor.line, cursor.ch);
    if (!substituteRange || !this._validateSelectionsContexts(substituteRange)) {
      this._hideSuggestBox();
      return;
    }

    const queryRange = substituteRange.clone();
    queryRange.endColumn = cursor.ch;
    const query = this._textEditor.text(queryRange);
    let hadSuggestBox = false;
    if (this._suggestBox) {
      hadSuggestBox = true;
    }
    this._wordsWithQuery(queryRange, substituteRange, force).then(wordsAcquired.bind(this));

    /**
     * @param {!UI.SuggestBox.Suggestions} wordsWithQuery
     * @this {TextEditorAutocompleteController}
     */
    function wordsAcquired(wordsWithQuery) {
      if (!wordsWithQuery.length || (wordsWithQuery.length === 1 && query === wordsWithQuery[0].text) ||
          (!this._suggestBox && hadSuggestBox)) {
        this._hideSuggestBox();
        this._onSuggestionsShownForTest([]);
        return;
      }
      if (!this._suggestBox) {
        this._suggestBox = new UI.SuggestBox(this, 20);
        if (this._config.anchorBehavior) {
          this._suggestBox.setAnchorBehavior(this._config.anchorBehavior);
        }
      }

      const oldQueryRange = this._queryRange;
      this._queryRange = queryRange;
      if (!oldQueryRange || queryRange.startLine !== oldQueryRange.startLine ||
          queryRange.startColumn !== oldQueryRange.startColumn) {
        this._updateAnchorBox();
      }
      this._suggestBox.updateSuggestions(this._anchorBox, wordsWithQuery, true, !this._isCursorAtEndOfLine(), query);
      if (this._suggestBox.visible) {
        this._tooltipGlassPane.hide();
      }
      this._onSuggestionsShownForTest(wordsWithQuery);
    }
  }

  /**
   * @param {string} hint
   */
  _setHint(hint) {
    const query = this._textEditor.text(this._queryRange);
    if (!hint || !this._isCursorAtEndOfLine() || !hint.startsWith(query)) {
      this._clearHint();
      return;
    }
    const suffix = hint.substring(query.length).split('\n')[0];
    this._hintElement.textContent = suffix.trimEndWithMaxLength(10000);
    const cursor = this._codeMirror.getCursor('to');
    if (this._hintMarker) {
      const position = this._hintMarker.position();
      if (!position || !position.equal(TextUtils.TextRange.createFromLocation(cursor.line, cursor.ch))) {
        this._hintMarker.clear();
        this._hintMarker = null;
      }
    }

    if (!this._hintMarker) {
      this._hintMarker = this._textEditor.addBookmark(
          cursor.line, cursor.ch, this._hintElement, TextEditorAutocompleteController.HintBookmark, true);
    } else if (this._lastHintText !== hint) {
      this._hintMarker.refresh();
    }
    this._lastHintText = hint;
  }

  _clearHint() {
    if (!this._hintElement.textContent) {
      return;
    }
    this._lastHintText = '';
    this._hintElement.textContent = '';
    if (this._hintMarker) {
      this._hintMarker.refresh();
    }
  }

  /**
   * @param {!UI.SuggestBox.Suggestions} suggestions
   */
  _onSuggestionsShownForTest(suggestions) {
  }

  _onSuggestionsHiddenForTest() {
  }

  clearAutocomplete() {
    this._tooltipGlassPane.hide();
    this._hideSuggestBox();
  }

  _hideSuggestBox() {
    if (!this._suggestBox) {
      return;
    }
    this._suggestBox.hide();
    this._suggestBox = null;
    this._queryRange = null;
    this._anchorBox = null;
    this._currentSuggestion = null;
    this._textEditor.dispatchEventToListeners(UI.TextEditor.Events.SuggestionChanged);
    this._clearHint();
    this._onSuggestionsHiddenForTest();
  }

  /**
   * @param {!KeyboardEvent} event
   * @return {boolean}
   */
  keyDown(event) {
    if (this._tooltipGlassPane.isShowing() && event.keyCode === UI.KeyboardShortcut.Keys.Esc.code) {
      this._tooltipGlassPane.hide();
      return true;
    }
    if (!this._suggestBox) {
      return false;
    }
    switch (event.keyCode) {
      case UI.KeyboardShortcut.Keys.Tab.code:
        this._suggestBox.acceptSuggestion();
        this.clearAutocomplete();
        return true;
      case UI.KeyboardShortcut.Keys.End.code:
      case UI.KeyboardShortcut.Keys.Right.code:
        if (this._isCursorAtEndOfLine()) {
          this._suggestBox.acceptSuggestion();
          this.clearAutocomplete();
          return true;
        } else {
          this.clearAutocomplete();
          return false;
        }
      case UI.KeyboardShortcut.Keys.Left.code:
      case UI.KeyboardShortcut.Keys.Home.code:
        this.clearAutocomplete();
        return false;
      case UI.KeyboardShortcut.Keys.Esc.code:
        this.clearAutocomplete();
        return true;
    }
    return this._suggestBox.keyPressed(event);
  }

  /**
   * @return {boolean}
   */
  _isCursorAtEndOfLine() {
    const cursor = this._codeMirror.getCursor('to');
    return cursor.ch === this._codeMirror.getLine(cursor.line).length;
  }

  /**
   * @override
   * @param {?UI.SuggestBox.Suggestion} suggestion
   * @param {boolean=} isIntermediateSuggestion
   */
  applySuggestion(suggestion, isIntermediateSuggestion) {
    const oldSuggestion = this._currentSuggestion;
    this._currentSuggestion = suggestion;
    this._setHint(suggestion ? suggestion.text : '');
    if ((oldSuggestion ? oldSuggestion.text : '') !== (suggestion ? suggestion.text : '')) {
      this._textEditor.dispatchEventToListeners(UI.TextEditor.Events.SuggestionChanged);
    }
  }

  /**
   * @override
   */
  acceptSuggestion() {
    const selections = this._codeMirror.listSelections().slice();
    const queryLength = this._queryRange.endColumn - this._queryRange.startColumn;
    const suggestion = this._currentSuggestion.text;
    this._codeMirror.operation(() => {
      for (let i = selections.length - 1; i >= 0; --i) {
        const start = selections[i].head;
        const end = new CodeMirror.Pos(start.line, start.ch - queryLength);
        this._codeMirror.replaceRange(suggestion, start, end, '+autocomplete');
      }
    });
  }

  /**
   * @return {string}
   */
  textWithCurrentSuggestion() {
    if (!this._queryRange || this._currentSuggestion === null) {
      return this._codeMirror.getValue();
    }

    const selections = this._codeMirror.listSelections().slice();
    let last = {line: 0, column: 0};
    let text = '';
    const queryLength = this._queryRange.endColumn - this._queryRange.startColumn;
    for (const selection of selections) {
      const range =
          new TextUtils.TextRange(last.line, last.column, selection.head.line, selection.head.ch - queryLength);
      text += this._textEditor.text(range);
      text += this._currentSuggestion.text;
      last = {line: selection.head.line, column: selection.head.ch};
    }
    const range = new TextUtils.TextRange(last.line, last.column, Infinity, Infinity);
    text += this._textEditor.text(range);
    return text;
  }

  _onScroll() {
    this._tooltipGlassPane.hide();
    if (!this._suggestBox) {
      return;
    }
    const cursor = this._codeMirror.getCursor();
    const scrollInfo = this._codeMirror.getScrollInfo();
    const topmostLineNumber = this._codeMirror.lineAtHeight(scrollInfo.top, 'local');
    const bottomLine = this._codeMirror.lineAtHeight(scrollInfo.top + scrollInfo.clientHeight, 'local');
    if (cursor.line < topmostLineNumber || cursor.line > bottomLine) {
      this.clearAutocomplete();
    } else {
      this._updateAnchorBox();
      this._suggestBox.setPosition(this._anchorBox);
    }
  }

  async _updateTooltip() {
    const cursor = this._codeMirror.getCursor();
    const tooltip = this._config.tooltipCallback ? await this._config.tooltipCallback(cursor.line, cursor.ch) : null;
    const newCursor = this._codeMirror.getCursor();

    if (newCursor.line !== cursor.line && newCursor.ch !== cursor.ch) {
      return;
    }
    if (this._suggestBox && this._suggestBox.visible) {
      return;
    }

    if (!tooltip) {
      this._tooltipGlassPane.hide();
      return;
    }
    const metrics = this._textEditor.cursorPositionToCoordinates(cursor.line, cursor.ch);
    if (!metrics) {
      this._tooltipGlassPane.hide();
      return;
    }

    this._tooltipGlassPane.setContentAnchorBox(new AnchorBox(metrics.x, metrics.y, 0, metrics.height));
    this._tooltipElement.removeChildren();
    this._tooltipElement.appendChild(tooltip);
    this._tooltipGlassPane.show(/** @type {!Document} */ (this._textEditor.element.ownerDocument));
  }

  _onCursorActivity() {
    this._updateTooltip();
    if (!this._suggestBox) {
      return;
    }
    const cursor = this._codeMirror.getCursor();
    let shouldCloseAutocomplete =
        !(cursor.line === this._queryRange.startLine && this._queryRange.startColumn <= cursor.ch &&
          cursor.ch <= this._queryRange.endColumn);
    // Try not to hide autocomplete when user types in.
    if (cursor.line === this._queryRange.startLine && cursor.ch === this._queryRange.endColumn + 1) {
      const line = this._codeMirror.getLine(cursor.line);
      shouldCloseAutocomplete = this._config.isWordChar ? !this._config.isWordChar(line.charAt(cursor.ch - 1)) : false;
    }
    if (shouldCloseAutocomplete) {
      this.clearAutocomplete();
    }
    this._onCursorActivityHandledForTest();
  }

  _onCursorActivityHandledForTest() {
  }

  _updateAnchorBox() {
    const line = this._queryRange.startLine;
    const column = this._queryRange.startColumn;
    const metrics = this._textEditor.cursorPositionToCoordinates(line, column);
    this._anchorBox = metrics ? new AnchorBox(metrics.x, metrics.y, 0, metrics.height) : null;
  }
}

TextEditorAutocompleteController.HintBookmark = Symbol('hint');

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

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

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