import { __require as requireDraftModifier } from './DraftModifier.js';
import { __require as requireDraftOffsetKey } from './DraftOffsetKey.js';
import { __require as requireEditorState } from './EditorState.js';
import { __require as requireUserAgent } from '../../../../fbjs@2.0.0/node_modules/fbjs/lib/UserAgent.js';
import { __require as requireDraftKeyUtils } from './draftKeyUtils.js';
import { __require as requireFindAncestorOffsetKey } from './findAncestorOffsetKey.js';
import { __require as requireKeyCommandPlainBackspace } from './keyCommandPlainBackspace.js';
import { __require as requireNullthrows } from '../../../../fbjs@2.0.0/node_modules/fbjs/lib/nullthrows.js';

/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @format
 * 
 * @emails oncall+draft_js
 */

var editOnInput_1;
var hasRequiredEditOnInput;

function requireEditOnInput () {
	if (hasRequiredEditOnInput) return editOnInput_1;
	hasRequiredEditOnInput = 1;

	var DraftModifier = requireDraftModifier();

	var DraftOffsetKey = requireDraftOffsetKey();

	var EditorState = requireEditorState();

	var UserAgent = requireUserAgent();

	var _require = requireDraftKeyUtils(),
	    notEmptyKey = _require.notEmptyKey;

	var findAncestorOffsetKey = requireFindAncestorOffsetKey();

	var keyCommandPlainBackspace = requireKeyCommandPlainBackspace();

	var nullthrows = requireNullthrows();

	var isGecko = UserAgent.isEngine('Gecko');
	var DOUBLE_NEWLINE = '\n\n';

	function onInputType(inputType, editorState) {
	  switch (inputType) {
	    case 'deleteContentBackward':
	      return keyCommandPlainBackspace(editorState);
	  }

	  return editorState;
	}
	/**
	 * This function serves two purposes
	 *
	 * 1. To update the editorState and call onChange method with the new
	 * editorState. This editorState is calculated in editOnBeforeInput but the
	 * onChange method is not called with the new state until this method does it.
	 * It is done to handle a specific case where certain character inputs might
	 * be replaced with something else. E.g. snippets ('rc' might be replaced
	 * with boilerplate code for react component). More information on the
	 * exact problem can be found here -
	 * https://github.com/facebook/draft-js/commit/07892ba479bd4dfc6afd1e0ed179aaf51cd138b1
	 *
	 * 2. intended to handle spellcheck and autocorrect changes,
	 * which occur in the DOM natively without any opportunity to observe or
	 * interpret the changes before they occur.
	 *
	 * The `input` event fires in contentEditable elements reliably for non-IE
	 * browsers, immediately after changes occur to the editor DOM. Since our other
	 * handlers override or otherwise handle cover other varieties of text input,
	 * the DOM state should match the model in all controlled input cases. Thus,
	 * when an `input` change leads to a DOM/model mismatch, the change should be
	 * due to a spellcheck change, and we can incorporate it into our model.
	 */


	function editOnInput(editor, e) {
	  if (editor._pendingStateFromBeforeInput !== undefined) {
	    editor.update(editor._pendingStateFromBeforeInput);
	    editor._pendingStateFromBeforeInput = undefined;
	  } // at this point editor is not null for sure (after input)


	  var castedEditorElement = editor.editor;
	  var domSelection = castedEditorElement.ownerDocument.defaultView.getSelection();
	  var anchorNode = domSelection.anchorNode,
	      isCollapsed = domSelection.isCollapsed;
	  var isNotTextOrElementNode = (anchorNode === null || anchorNode === void 0 ? void 0 : anchorNode.nodeType) !== Node.TEXT_NODE && (anchorNode === null || anchorNode === void 0 ? void 0 : anchorNode.nodeType) !== Node.ELEMENT_NODE;

	  if (anchorNode == null || isNotTextOrElementNode) {
	    // TODO: (t16149272) figure out context for this change
	    return;
	  }

	  if (anchorNode.nodeType === Node.TEXT_NODE && (anchorNode.previousSibling !== null || anchorNode.nextSibling !== null)) {
	    // When typing at the beginning of a visual line, Chrome splits the text
	    // nodes into two. Why? No one knows. This commit is suspicious:
	    // https://chromium.googlesource.com/chromium/src/+/a3b600981286b135632371477f902214c55a1724
	    // To work around, we'll merge the sibling text nodes back into this one.
	    var span = anchorNode.parentNode;

	    if (span == null) {
	      // Handle null-parent case.
	      return;
	    }

	    anchorNode.nodeValue = span.textContent;

	    for (var child = span.firstChild; child != null; child = child.nextSibling) {
	      if (child !== anchorNode) {
	        span.removeChild(child);
	      }
	    }
	  }

	  var domText = anchorNode.textContent;
	  var editorState = editor._latestEditorState;
	  var offsetKey = nullthrows(findAncestorOffsetKey(anchorNode));

	  var _DraftOffsetKey$decod = DraftOffsetKey.decode(offsetKey),
	      blockKey = _DraftOffsetKey$decod.blockKey,
	      decoratorKey = _DraftOffsetKey$decod.decoratorKey,
	      leafKey = _DraftOffsetKey$decod.leafKey;

	  var _editorState$getBlock = editorState.getBlockTree(blockKey).getIn([decoratorKey, 'leaves', leafKey]),
	      start = _editorState$getBlock.start,
	      end = _editorState$getBlock.end;

	  var content = editorState.getCurrentContent();
	  var block = content.getBlockForKey(blockKey);
	  var modelText = block.getText().slice(start, end); // Special-case soft newlines here. If the DOM text ends in a soft newline,
	  // we will have manually inserted an extra soft newline in DraftEditorLeaf.
	  // We want to remove this extra newline for the purpose of our comparison
	  // of DOM and model text.

	  if (domText.endsWith(DOUBLE_NEWLINE)) {
	    domText = domText.slice(0, -1);
	  } // No change -- the DOM is up to date. Nothing to do here.


	  if (domText === modelText) {
	    // This can be buggy for some Android keyboards because they don't fire
	    // standard onkeydown/pressed events and only fired editOnInput
	    // so domText is already changed by the browser and ends up being equal
	    // to modelText unexpectedly.
	    // Newest versions of Android support the dom-inputevent-inputtype
	    // and we can use the `inputType` to properly apply the state changes.

	    /* $FlowFixMe[prop-missing] inputType is only defined on a draft of a
	     * standard. https://w3c.github.io/input-events/#dom-inputevent-inputtype
	     */
	    var inputType = e.nativeEvent.inputType;

	    if (inputType) {
	      var newEditorState = onInputType(inputType, editorState);

	      if (newEditorState !== editorState) {
	        editor.restoreEditorDOM();
	        editor.update(newEditorState);
	        return;
	      }
	    }

	    return;
	  }

	  var selection = editorState.getSelection(); // We'll replace the entire leaf with the text content of the target.

	  var targetRange = selection.merge({
	    anchorOffset: start,
	    focusOffset: end,
	    isBackward: false
	  });
	  var entityKey = block.getEntityAt(start);
	  var entity = notEmptyKey(entityKey) ? content.getEntity(entityKey) : null;
	  var entityType = entity != null ? entity.getMutability() : null;
	  var preserveEntity = entityType === 'MUTABLE'; // Immutable or segmented entities cannot properly be handled by the
	  // default browser undo, so we have to use a different change type to
	  // force using our internal undo method instead of falling through to the
	  // native browser undo.

	  var changeType = preserveEntity ? 'spellcheck-change' : 'apply-entity';
	  var newContent = DraftModifier.replaceText(content, targetRange, domText, block.getInlineStyleAt(start), preserveEntity ? block.getEntityAt(start) : null);
	  var anchorOffset, focusOffset, startOffset, endOffset;

	  if (isGecko) {
	    // Firefox selection does not change while the context menu is open, so
	    // we preserve the anchor and focus values of the DOM selection.
	    anchorOffset = domSelection.anchorOffset;
	    focusOffset = domSelection.focusOffset;
	    startOffset = start + Math.min(anchorOffset, focusOffset);
	    endOffset = startOffset + Math.abs(anchorOffset - focusOffset);
	    anchorOffset = startOffset;
	    focusOffset = endOffset;
	  } else {
	    // Browsers other than Firefox may adjust DOM selection while the context
	    // menu is open, and Safari autocorrect is prone to providing an inaccurate
	    // DOM selection. Don't trust it. Instead, use our existing SelectionState
	    // and adjust it based on the number of characters changed during the
	    // mutation.
	    var charDelta = domText.length - modelText.length;
	    startOffset = selection.getStartOffset();
	    endOffset = selection.getEndOffset();
	    anchorOffset = isCollapsed ? endOffset + charDelta : startOffset;
	    focusOffset = endOffset + charDelta;
	  } // Segmented entities are completely or partially removed when their
	  // text content changes. For this case we do not want any text to be selected
	  // after the change, so we are not merging the selection.


	  var contentWithAdjustedDOMSelection = newContent.merge({
	    selectionBefore: content.getSelectionAfter(),
	    selectionAfter: selection.merge({
	      anchorOffset: anchorOffset,
	      focusOffset: focusOffset
	    })
	  });
	  editor.update(EditorState.push(editorState, contentWithAdjustedDOMSelection, changeType));
	}

	editOnInput_1 = editOnInput;
	return editOnInput_1;
}

export { requireEditOnInput as __require };
//# sourceMappingURL=editOnInput.js.map
