"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const browser = require("../../../base/browser/browser.js");
const dom = require("../../../base/browser/dom.js");
const keyboardEvent = require("../../../base/browser/keyboardEvent.js");
const async = require("../../../base/common/async.js");
const event = require("../../../base/common/event.js");
const lifecycle = require("../../../base/common/lifecycle.js");
const mime = require("../../../base/common/mime.js");
const strings = require("../../../base/common/strings.js");
const textAreaState = require("./textAreaState.js");
const selection = require("../../common/core/selection.js");
exports.TextAreaSyntethicEvents = void 0;
(function(TextAreaSyntethicEvents) {
  TextAreaSyntethicEvents.Tap = "-monaco-textarea-synthetic-tap";
})(exports.TextAreaSyntethicEvents || (exports.TextAreaSyntethicEvents = {}));
const CopyOptions = {
  forceCopyWithSyntaxHighlighting: false
};
class InMemoryClipboardMetadataManager {
  constructor() {
    this._lastState = null;
  }
  set(lastCopiedValue, data) {
    this._lastState = { lastCopiedValue, data };
  }
  get(pastedText) {
    if (this._lastState && this._lastState.lastCopiedValue === pastedText) {
      return this._lastState.data;
    }
    this._lastState = null;
    return null;
  }
}
InMemoryClipboardMetadataManager.INSTANCE = new InMemoryClipboardMetadataManager();
class CompositionContext {
  constructor() {
    this._lastTypeTextLength = 0;
  }
  handleCompositionUpdate(text) {
    text = text || "";
    const typeInput = {
      text,
      replacePrevCharCnt: this._lastTypeTextLength,
      replaceNextCharCnt: 0,
      positionDelta: 0
    };
    this._lastTypeTextLength = text.length;
    return typeInput;
  }
}
class TextAreaInput extends lifecycle.Disposable {
  constructor(_host, _textArea, _OS, _browser) {
    super();
    this._host = _host;
    this._textArea = _textArea;
    this._OS = _OS;
    this._browser = _browser;
    this._onFocus = this._register(new event.Emitter());
    this.onFocus = this._onFocus.event;
    this._onBlur = this._register(new event.Emitter());
    this.onBlur = this._onBlur.event;
    this._onKeyDown = this._register(new event.Emitter());
    this.onKeyDown = this._onKeyDown.event;
    this._onKeyUp = this._register(new event.Emitter());
    this.onKeyUp = this._onKeyUp.event;
    this._onCut = this._register(new event.Emitter());
    this.onCut = this._onCut.event;
    this._onPaste = this._register(new event.Emitter());
    this.onPaste = this._onPaste.event;
    this._onType = this._register(new event.Emitter());
    this.onType = this._onType.event;
    this._onCompositionStart = this._register(new event.Emitter());
    this.onCompositionStart = this._onCompositionStart.event;
    this._onCompositionUpdate = this._register(new event.Emitter());
    this.onCompositionUpdate = this._onCompositionUpdate.event;
    this._onCompositionEnd = this._register(new event.Emitter());
    this.onCompositionEnd = this._onCompositionEnd.event;
    this._onSelectionChangeRequest = this._register(new event.Emitter());
    this.onSelectionChangeRequest = this._onSelectionChangeRequest.event;
    this._asyncTriggerCut = this._register(new async.RunOnceScheduler(() => this._onCut.fire(), 0));
    this._asyncFocusGainWriteScreenReaderContent = this._register(new async.RunOnceScheduler(() => this.writeScreenReaderContent("asyncFocusGain"), 0));
    this._textAreaState = textAreaState.TextAreaState.EMPTY;
    this._selectionChangeListener = null;
    this.writeScreenReaderContent("ctor");
    this._hasFocus = false;
    this._currentComposition = null;
    let lastKeyDown = null;
    this._register(this._textArea.onKeyDown((_e) => {
      const e = new keyboardEvent.StandardKeyboardEvent(_e);
      if (e.keyCode === 109 || this._currentComposition && e.keyCode === 1) {
        e.stopPropagation();
      }
      if (e.equals(
        9
        /* Escape */
      )) {
        e.preventDefault();
      }
      lastKeyDown = e;
      this._onKeyDown.fire(e);
    }));
    this._register(this._textArea.onKeyUp((_e) => {
      const e = new keyboardEvent.StandardKeyboardEvent(_e);
      this._onKeyUp.fire(e);
    }));
    this._register(this._textArea.onCompositionStart((e) => {
      const currentComposition = new CompositionContext();
      if (this._currentComposition) {
        this._currentComposition = currentComposition;
        return;
      }
      this._currentComposition = currentComposition;
      if (this._OS === 2 && lastKeyDown && lastKeyDown.equals(
        109
        /* KEY_IN_COMPOSITION */
      ) && this._textAreaState.selectionStart === this._textAreaState.selectionEnd && this._textAreaState.selectionStart > 0 && this._textAreaState.value.substr(this._textAreaState.selectionStart - 1, 1) === e.data && (lastKeyDown.code === "ArrowRight" || lastKeyDown.code === "ArrowLeft")) {
        currentComposition.handleCompositionUpdate("x");
        this._onCompositionStart.fire({ data: e.data });
        return;
      }
      if (this._browser.isAndroid) {
        this._onCompositionStart.fire({ data: e.data });
        return;
      }
      this._onCompositionStart.fire({ data: e.data });
    }));
    this._register(this._textArea.onCompositionUpdate((e) => {
      const currentComposition = this._currentComposition;
      if (!currentComposition) {
        return;
      }
      if (this._browser.isAndroid) {
        const newState = textAreaState.TextAreaState.readFromTextArea(this._textArea);
        const typeInput2 = textAreaState.TextAreaState.deduceAndroidCompositionInput(this._textAreaState, newState);
        this._textAreaState = newState;
        this._onType.fire(typeInput2);
        this._onCompositionUpdate.fire(e);
        return;
      }
      const typeInput = currentComposition.handleCompositionUpdate(e.data);
      this._textAreaState = textAreaState.TextAreaState.readFromTextArea(this._textArea);
      this._onType.fire(typeInput);
      this._onCompositionUpdate.fire(e);
    }));
    this._register(this._textArea.onCompositionEnd((e) => {
      const currentComposition = this._currentComposition;
      if (!currentComposition) {
        return;
      }
      this._currentComposition = null;
      if (this._browser.isAndroid) {
        const newState = textAreaState.TextAreaState.readFromTextArea(this._textArea);
        const typeInput2 = textAreaState.TextAreaState.deduceAndroidCompositionInput(this._textAreaState, newState);
        this._textAreaState = newState;
        this._onType.fire(typeInput2);
        this._onCompositionEnd.fire();
        return;
      }
      const typeInput = currentComposition.handleCompositionUpdate(e.data);
      this._textAreaState = textAreaState.TextAreaState.readFromTextArea(this._textArea);
      this._onType.fire(typeInput);
      this._onCompositionEnd.fire();
    }));
    this._register(this._textArea.onInput((e) => {
      this._textArea.setIgnoreSelectionChangeTime("received input event");
      if (this._currentComposition) {
        return;
      }
      const newState = textAreaState.TextAreaState.readFromTextArea(this._textArea);
      const typeInput = textAreaState.TextAreaState.deduceInput(
        this._textAreaState,
        newState,
        /*couldBeEmojiInput*/
        this._OS === 2
        /* Macintosh */
      );
      if (typeInput.replacePrevCharCnt === 0 && typeInput.text.length === 1 && strings.isHighSurrogate(typeInput.text.charCodeAt(0))) {
        return;
      }
      this._textAreaState = newState;
      if (typeInput.text !== "" || typeInput.replacePrevCharCnt !== 0 || typeInput.replaceNextCharCnt !== 0 || typeInput.positionDelta !== 0) {
        this._onType.fire(typeInput);
      }
    }));
    this._register(this._textArea.onCut((e) => {
      this._textArea.setIgnoreSelectionChangeTime("received cut event");
      this._ensureClipboardGetsEditorSelection(e);
      this._asyncTriggerCut.schedule();
    }));
    this._register(this._textArea.onCopy((e) => {
      this._ensureClipboardGetsEditorSelection(e);
    }));
    this._register(this._textArea.onPaste((e) => {
      this._textArea.setIgnoreSelectionChangeTime("received paste event");
      e.preventDefault();
      if (!e.clipboardData) {
        return;
      }
      let [text, metadata] = ClipboardEventUtils.getTextData(e.clipboardData);
      if (!text) {
        return;
      }
      metadata = metadata || InMemoryClipboardMetadataManager.INSTANCE.get(text);
      this._onPaste.fire({
        text,
        metadata
      });
    }));
    this._register(this._textArea.onFocus(() => {
      const hadFocus = this._hasFocus;
      this._setHasFocus(true);
      if (this._browser.isSafari && !hadFocus && this._hasFocus) {
        this._asyncFocusGainWriteScreenReaderContent.schedule();
      }
    }));
    this._register(this._textArea.onBlur(() => {
      if (this._currentComposition) {
        this._currentComposition = null;
        this.writeScreenReaderContent("blurWithoutCompositionEnd");
        this._onCompositionEnd.fire();
      }
      this._setHasFocus(false);
    }));
    this._register(this._textArea.onSyntheticTap(() => {
      if (this._browser.isAndroid && this._currentComposition) {
        this._currentComposition = null;
        this.writeScreenReaderContent("tapWithoutCompositionEnd");
        this._onCompositionEnd.fire();
      }
    }));
  }
  _installSelectionChangeListener() {
    let previousSelectionChangeEventTime = 0;
    return dom.addDisposableListener(document, "selectionchange", (e) => {
      if (!this._hasFocus) {
        return;
      }
      if (this._currentComposition) {
        return;
      }
      if (!this._browser.isChrome) {
        return;
      }
      const now = Date.now();
      const delta1 = now - previousSelectionChangeEventTime;
      previousSelectionChangeEventTime = now;
      if (delta1 < 5) {
        return;
      }
      const delta2 = now - this._textArea.getIgnoreSelectionChangeTime();
      this._textArea.resetSelectionChangeTime();
      if (delta2 < 100) {
        return;
      }
      if (!this._textAreaState.selectionStartPosition || !this._textAreaState.selectionEndPosition) {
        return;
      }
      const newValue = this._textArea.getValue();
      if (this._textAreaState.value !== newValue) {
        return;
      }
      const newSelectionStart = this._textArea.getSelectionStart();
      const newSelectionEnd = this._textArea.getSelectionEnd();
      if (this._textAreaState.selectionStart === newSelectionStart && this._textAreaState.selectionEnd === newSelectionEnd) {
        return;
      }
      const _newSelectionStartPosition = this._textAreaState.deduceEditorPosition(newSelectionStart);
      const newSelectionStartPosition = this._host.deduceModelPosition(_newSelectionStartPosition[0], _newSelectionStartPosition[1], _newSelectionStartPosition[2]);
      const _newSelectionEndPosition = this._textAreaState.deduceEditorPosition(newSelectionEnd);
      const newSelectionEndPosition = this._host.deduceModelPosition(_newSelectionEndPosition[0], _newSelectionEndPosition[1], _newSelectionEndPosition[2]);
      const newSelection = new selection.Selection(newSelectionStartPosition.lineNumber, newSelectionStartPosition.column, newSelectionEndPosition.lineNumber, newSelectionEndPosition.column);
      this._onSelectionChangeRequest.fire(newSelection);
    });
  }
  dispose() {
    super.dispose();
    if (this._selectionChangeListener) {
      this._selectionChangeListener.dispose();
      this._selectionChangeListener = null;
    }
  }
  focusTextArea() {
    this._setHasFocus(true);
    this.refreshFocusState();
  }
  isFocused() {
    return this._hasFocus;
  }
  refreshFocusState() {
    this._setHasFocus(this._textArea.hasFocus());
  }
  _setHasFocus(newHasFocus) {
    if (this._hasFocus === newHasFocus) {
      return;
    }
    this._hasFocus = newHasFocus;
    if (this._selectionChangeListener) {
      this._selectionChangeListener.dispose();
      this._selectionChangeListener = null;
    }
    if (this._hasFocus) {
      this._selectionChangeListener = this._installSelectionChangeListener();
    }
    if (this._hasFocus) {
      this.writeScreenReaderContent("focusgain");
    }
    if (this._hasFocus) {
      this._onFocus.fire();
    } else {
      this._onBlur.fire();
    }
  }
  _setAndWriteTextAreaState(reason, textAreaState2) {
    if (!this._hasFocus) {
      textAreaState2 = textAreaState2.collapseSelection();
    }
    textAreaState2.writeToTextArea(reason, this._textArea, this._hasFocus);
    this._textAreaState = textAreaState2;
  }
  writeScreenReaderContent(reason) {
    if (this._currentComposition) {
      return;
    }
    this._setAndWriteTextAreaState(reason, this._host.getScreenReaderContent(this._textAreaState));
  }
  _ensureClipboardGetsEditorSelection(e) {
    const dataToCopy = this._host.getDataToCopy();
    const storedMetadata = {
      version: 1,
      isFromEmptySelection: dataToCopy.isFromEmptySelection,
      multicursorText: dataToCopy.multicursorText,
      mode: dataToCopy.mode
    };
    InMemoryClipboardMetadataManager.INSTANCE.set(
      // When writing "LINE\r\n" to the clipboard and then pasting,
      // Firefox pastes "LINE\n", so let's work around this quirk
      this._browser.isFirefox ? dataToCopy.text.replace(/\r\n/g, "\n") : dataToCopy.text,
      storedMetadata
    );
    e.preventDefault();
    if (e.clipboardData) {
      ClipboardEventUtils.setTextData(e.clipboardData, dataToCopy.text, dataToCopy.html, storedMetadata);
    }
  }
}
class ClipboardEventUtils {
  static getTextData(clipboardData) {
    const text = clipboardData.getData(mime.Mimes.text);
    let metadata = null;
    const rawmetadata = clipboardData.getData("vscode-editor-data");
    if (typeof rawmetadata === "string") {
      try {
        metadata = JSON.parse(rawmetadata);
        if (metadata.version !== 1) {
          metadata = null;
        }
      } catch (err) {
      }
    }
    return [text, metadata];
  }
  static setTextData(clipboardData, text, html, metadata) {
    clipboardData.setData(mime.Mimes.text, text);
    if (typeof html === "string") {
      clipboardData.setData("text/html", html);
    }
    clipboardData.setData("vscode-editor-data", JSON.stringify(metadata));
  }
}
class TextAreaWrapper extends lifecycle.Disposable {
  constructor(_actual) {
    super();
    this._actual = _actual;
    this.onKeyDown = this._register(dom.createEventEmitter(this._actual, "keydown")).event;
    this.onKeyUp = this._register(dom.createEventEmitter(this._actual, "keyup")).event;
    this.onCompositionStart = this._register(dom.createEventEmitter(this._actual, "compositionstart")).event;
    this.onCompositionUpdate = this._register(dom.createEventEmitter(this._actual, "compositionupdate")).event;
    this.onCompositionEnd = this._register(dom.createEventEmitter(this._actual, "compositionend")).event;
    this.onInput = this._register(dom.createEventEmitter(this._actual, "input")).event;
    this.onCut = this._register(dom.createEventEmitter(this._actual, "cut")).event;
    this.onCopy = this._register(dom.createEventEmitter(this._actual, "copy")).event;
    this.onPaste = this._register(dom.createEventEmitter(this._actual, "paste")).event;
    this.onFocus = this._register(dom.createEventEmitter(this._actual, "focus")).event;
    this.onBlur = this._register(dom.createEventEmitter(this._actual, "blur")).event;
    this._onSyntheticTap = this._register(new event.Emitter());
    this.onSyntheticTap = this._onSyntheticTap.event;
    this._ignoreSelectionChangeTime = 0;
    this._register(dom.addDisposableListener(this._actual, exports.TextAreaSyntethicEvents.Tap, () => this._onSyntheticTap.fire()));
  }
  hasFocus() {
    const shadowRoot = dom.getShadowRoot(this._actual);
    if (shadowRoot) {
      return shadowRoot.activeElement === this._actual;
    } else if (dom.isInDOM(this._actual)) {
      return document.activeElement === this._actual;
    } else {
      return false;
    }
  }
  setIgnoreSelectionChangeTime(reason) {
    this._ignoreSelectionChangeTime = Date.now();
  }
  getIgnoreSelectionChangeTime() {
    return this._ignoreSelectionChangeTime;
  }
  resetSelectionChangeTime() {
    this._ignoreSelectionChangeTime = 0;
  }
  getValue() {
    return this._actual.value;
  }
  setValue(reason, value) {
    const textArea = this._actual;
    if (textArea.value === value) {
      return;
    }
    this.setIgnoreSelectionChangeTime("setValue");
    textArea.value = value;
  }
  getSelectionStart() {
    return this._actual.selectionDirection === "backward" ? this._actual.selectionEnd : this._actual.selectionStart;
  }
  getSelectionEnd() {
    return this._actual.selectionDirection === "backward" ? this._actual.selectionStart : this._actual.selectionEnd;
  }
  setSelectionRange(reason, selectionStart, selectionEnd) {
    const textArea = this._actual;
    let activeElement = null;
    const shadowRoot = dom.getShadowRoot(textArea);
    if (shadowRoot) {
      activeElement = shadowRoot.activeElement;
    } else {
      activeElement = document.activeElement;
    }
    const currentIsFocused = activeElement === textArea;
    const currentSelectionStart = textArea.selectionStart;
    const currentSelectionEnd = textArea.selectionEnd;
    if (currentIsFocused && currentSelectionStart === selectionStart && currentSelectionEnd === selectionEnd) {
      if (browser.isFirefox && window.parent !== window) {
        textArea.focus();
      }
      return;
    }
    if (currentIsFocused) {
      this.setIgnoreSelectionChangeTime("setSelectionRange");
      textArea.setSelectionRange(selectionStart, selectionEnd);
      if (browser.isFirefox && window.parent !== window) {
        textArea.focus();
      }
      return;
    }
    try {
      const scrollState = dom.saveParentsScrollTop(textArea);
      this.setIgnoreSelectionChangeTime("setSelectionRange");
      textArea.focus();
      textArea.setSelectionRange(selectionStart, selectionEnd);
      dom.restoreParentsScrollTop(textArea, scrollState);
    } catch (e) {
    }
  }
}
exports.CopyOptions = CopyOptions;
exports.InMemoryClipboardMetadataManager = InMemoryClipboardMetadataManager;
exports.TextAreaInput = TextAreaInput;
exports.TextAreaWrapper = TextAreaWrapper;
