import { __require as requireDOMObserver } from './DOMObserver.js';
import { __require as requireDraftModifier } from './DraftModifier.js';
import { __require as requireDraftOffsetKey } from './DraftOffsetKey.js';
import { __require as requireEditorState } from './EditorState.js';
import { __require as requireKeys } from '../../../../fbjs@2.0.0/node_modules/fbjs/lib/Keys.js';
import { __require as requireUserAgent } from '../../../../fbjs@2.0.0/node_modules/fbjs/lib/UserAgent.js';
import { __require as requireEditOnSelect } from './editOnSelect.js';
import { __require as requireGetContentEditableContainer } from './getContentEditableContainer.js';
import { __require as requireGetDraftEditorSelection } from './getDraftEditorSelection.js';
import { __require as requireGetEntityKeyForSelection } from './getEntityKeyForSelection.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 DraftEditorCompositionHandler_1;
var hasRequiredDraftEditorCompositionHandler;

function requireDraftEditorCompositionHandler () {
	if (hasRequiredDraftEditorCompositionHandler) return DraftEditorCompositionHandler_1;
	hasRequiredDraftEditorCompositionHandler = 1;

	var DOMObserver = requireDOMObserver();

	var DraftModifier = requireDraftModifier();

	var DraftOffsetKey = requireDraftOffsetKey();

	var EditorState = requireEditorState();

	var Keys = requireKeys();

	var UserAgent = requireUserAgent();

	var editOnSelect = requireEditOnSelect();

	var getContentEditableContainer = requireGetContentEditableContainer();

	var getDraftEditorSelection = requireGetDraftEditorSelection();

	var getEntityKeyForSelection = requireGetEntityKeyForSelection();

	var nullthrows = requireNullthrows();

	var isIE = UserAgent.isBrowser('IE');
	/**
	 * Millisecond delay to allow `compositionstart` to fire again upon
	 * `compositionend`.
	 *
	 * This is used for Korean input to ensure that typing can continue without
	 * the editor trying to render too quickly. More specifically, Safari 7.1+
	 * triggers `compositionstart` a little slower than Chrome/FF, which
	 * leads to composed characters being resolved and re-render occurring
	 * sooner than we want.
	 */

	var RESOLVE_DELAY = 20;
	/**
	 * A handful of variables used to track the current composition and its
	 * resolution status. These exist at the module level because it is not
	 * possible to have compositions occurring in multiple editors simultaneously,
	 * and it simplifies state management with respect to the DraftEditor component.
	 */

	var resolved = false;
	var stillComposing = false;
	var domObserver = null;

	function startDOMObserver(editor) {
	  if (!domObserver) {
	    domObserver = new DOMObserver(getContentEditableContainer(editor));
	    domObserver.start();
	  }
	}

	var DraftEditorCompositionHandler = {
	  /**
	   * A `compositionstart` event has fired while we're still in composition
	   * mode. Continue the current composition session to prevent a re-render.
	   */
	  onCompositionStart: function onCompositionStart(editor) {
	    stillComposing = true;
	    startDOMObserver(editor);
	  },

	  /**
	   * Attempt to end the current composition session.
	   *
	   * Defer handling because browser will still insert the chars into active
	   * element after `compositionend`. If a `compositionstart` event fires
	   * before `resolveComposition` executes, our composition session will
	   * continue.
	   *
	   * The `resolved` flag is useful because certain IME interfaces fire the
	   * `compositionend` event multiple times, thus queueing up multiple attempts
	   * at handling the composition. Since handling the same composition event
	   * twice could break the DOM, we only use the first event. Example: Arabic
	   * Google Input Tools on Windows 8.1 fires `compositionend` three times.
	   */
	  onCompositionEnd: function onCompositionEnd(editor) {
	    resolved = false;
	    stillComposing = false;
	    setTimeout(function () {
	      if (!resolved) {
	        DraftEditorCompositionHandler.resolveComposition(editor);
	      }
	    }, RESOLVE_DELAY);
	  },
	  onSelect: editOnSelect,

	  /**
	   * In Safari, keydown events may fire when committing compositions. If
	   * the arrow keys are used to commit, prevent default so that the cursor
	   * doesn't move, otherwise it will jump back noticeably on re-render.
	   */
	  onKeyDown: function onKeyDown(editor, e) {
	    if (!stillComposing) {
	      // If a keydown event is received after compositionend but before the
	      // 20ms timer expires (ex: type option-E then backspace, or type A then
	      // backspace in 2-Set Korean), we should immediately resolve the
	      // composition and reinterpret the key press in edit mode.
	      DraftEditorCompositionHandler.resolveComposition(editor);

	      editor._onKeyDown(e);

	      return;
	    }

	    if (e.which === Keys.RIGHT || e.which === Keys.LEFT) {
	      e.preventDefault();
	    }
	  },

	  /**
	   * Keypress events may fire when committing compositions. In Firefox,
	   * pressing RETURN commits the composition and inserts extra newline
	   * characters that we do not want. `preventDefault` allows the composition
	   * to be committed while preventing the extra characters.
	   */
	  onKeyPress: function onKeyPress(_editor, e) {
	    if (e.which === Keys.RETURN) {
	      e.preventDefault();
	    }
	  },

	  /**
	   * Attempt to insert composed characters into the document.
	   *
	   * If we are still in a composition session, do nothing. Otherwise, insert
	   * the characters into the document and terminate the composition session.
	   *
	   * If no characters were composed -- for instance, the user
	   * deleted all composed characters and committed nothing new --
	   * force a re-render. We also re-render when the composition occurs
	   * at the beginning of a leaf, to ensure that if the browser has
	   * created a new text node for the composition, we will discard it.
	   *
	   * Resetting innerHTML will move focus to the beginning of the editor,
	   * so we update to force it back to the correct place.
	   */
	  resolveComposition: function resolveComposition(editor) {
	    if (stillComposing) {
	      return;
	    }

	    var mutations = nullthrows(domObserver).stopAndFlushMutations();
	    domObserver = null;
	    resolved = true;
	    var editorState = EditorState.set(editor._latestEditorState, {
	      inCompositionMode: false
	    });
	    editor.exitCurrentMode();

	    if (!mutations.size) {
	      editor.update(editorState);
	      return;
	    } // TODO, check if Facebook still needs this flag or if it could be removed.
	    // Since there can be multiple mutations providing a `composedChars` doesn't
	    // apply well on this new model.
	    // if (
	    //   gkx('draft_handlebeforeinput_composed_text') &&
	    //   editor.props.handleBeforeInput &&
	    //   isEventHandled(
	    //     editor.props.handleBeforeInput(
	    //       composedChars,
	    //       editorState,
	    //       event.timeStamp,
	    //     ),
	    //   )
	    // ) {
	    //   return;
	    // }


	    var contentState = editorState.getCurrentContent();
	    mutations.forEach(function (composedChars, offsetKey) {
	      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 replacementRange = editorState.getSelection().merge({
	        anchorKey: blockKey,
	        focusKey: blockKey,
	        anchorOffset: start,
	        focusOffset: end,
	        isBackward: false
	      });
	      var entityKey = getEntityKeyForSelection(contentState, replacementRange);
	      var currentStyle = contentState.getBlockForKey(blockKey).getInlineStyleAt(start);
	      contentState = DraftModifier.replaceText(contentState, replacementRange, composedChars, currentStyle, entityKey); // We need to update the editorState so the leaf node ranges are properly
	      // updated and multiple mutations are correctly applied.

	      editorState = EditorState.set(editorState, {
	        currentContent: contentState
	      });
	    }); // When we apply the text changes to the ContentState, the selection always
	    // goes to the end of the field, but it should just stay where it is
	    // after compositionEnd.

	    var documentSelection = getDraftEditorSelection(editorState, getContentEditableContainer(editor));
	    var compositionEndSelectionState = documentSelection.selectionState;
	    editor.restoreEditorDOM(); // See:
	    // - https://github.com/facebook/draft-js/issues/2093
	    // - https://github.com/facebook/draft-js/pull/2094
	    // Apply this fix only in IE for now. We can test it in
	    // other browsers in the future to ensure no regressions

	    var editorStateWithUpdatedSelection = isIE ? EditorState.forceSelection(editorState, compositionEndSelectionState) : EditorState.acceptSelection(editorState, compositionEndSelectionState);
	    editor.update(EditorState.push(editorStateWithUpdatedSelection, contentState, 'insert-characters'));
	  }
	};
	DraftEditorCompositionHandler_1 = DraftEditorCompositionHandler;
	return DraftEditorCompositionHandler_1;
}

export { requireDraftEditorCompositionHandler as __require };
//# sourceMappingURL=DraftEditorCompositionHandler.js.map
