import { __require as requireBlockTree } from './BlockTree.js';
import { __require as requireContentState } from './ContentState.js';
import { __require as requireEditorBidiService } from './EditorBidiService.js';
import { __require as requireSelectionState } from './SelectionState.js';
import { __require as requireImmutable } from '../../../../immutable@3.7.6/node_modules/immutable/dist/immutable.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 EditorState_1;
var hasRequiredEditorState;

function requireEditorState () {
	if (hasRequiredEditorState) return EditorState_1;
	hasRequiredEditorState = 1;

	function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }

	function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

	var BlockTree = requireBlockTree();

	var ContentState = requireContentState();

	var EditorBidiService = requireEditorBidiService();

	var SelectionState = requireSelectionState();

	var Immutable = requireImmutable();

	var OrderedSet = Immutable.OrderedSet,
	    Record = Immutable.Record,
	    Stack = Immutable.Stack,
	    OrderedMap = Immutable.OrderedMap,
	    List = Immutable.List; // When configuring an editor, the user can chose to provide or not provide
	// basically all keys. `currentContent` varies, so this type doesn't include it.
	// (See the types defined below.)

	var defaultRecord = {
	  allowUndo: true,
	  currentContent: null,
	  decorator: null,
	  directionMap: null,
	  forceSelection: false,
	  inCompositionMode: false,
	  inlineStyleOverride: null,
	  lastChangeType: null,
	  nativelyRenderedContent: null,
	  redoStack: Stack(),
	  selection: null,
	  treeMap: null,
	  undoStack: Stack()
	};
	var EditorStateRecord = Record(defaultRecord);

	var EditorState = /*#__PURE__*/function () {
	  EditorState.createEmpty = function createEmpty(decorator) {
	    return this.createWithText('', decorator);
	  };

	  EditorState.createWithText = function createWithText(text, decorator) {
	    return EditorState.createWithContent(ContentState.createFromText(text), decorator);
	  };

	  EditorState.createWithContent = function createWithContent(contentState, decorator) {
	    if (contentState.getBlockMap().count() === 0) {
	      return EditorState.createEmpty(decorator);
	    }

	    var firstKey = contentState.getBlockMap().first().getKey();
	    return EditorState.create({
	      currentContent: contentState,
	      undoStack: Stack(),
	      redoStack: Stack(),
	      decorator: decorator || null,
	      selection: SelectionState.createEmpty(firstKey)
	    });
	  };

	  EditorState.create = function create(config) {
	    var currentContent = config.currentContent,
	        decorator = config.decorator;

	    var recordConfig = _objectSpread({}, config, {
	      treeMap: generateNewTreeMap(currentContent, decorator),
	      directionMap: EditorBidiService.getDirectionMap(currentContent)
	    });

	    return new EditorState(new EditorStateRecord(recordConfig));
	  };

	  EditorState.fromJS = function fromJS(config) {
	    return new EditorState(new EditorStateRecord(_objectSpread({}, config, {
	      directionMap: config.directionMap != null ? OrderedMap(config.directionMap) : config.directionMap,
	      inlineStyleOverride: config.inlineStyleOverride != null ? OrderedSet(config.inlineStyleOverride) : config.inlineStyleOverride,
	      nativelyRenderedContent: config.nativelyRenderedContent != null ? ContentState.fromJS(config.nativelyRenderedContent) : config.nativelyRenderedContent,
	      redoStack: config.redoStack != null ? Stack(config.redoStack.map(function (v) {
	        return ContentState.fromJS(v);
	      })) : config.redoStack,
	      selection: config.selection != null ? new SelectionState(config.selection) : config.selection,
	      treeMap: config.treeMap != null ? OrderedMap(config.treeMap).map(function (v) {
	        return List(v).map(function (v) {
	          return BlockTree.fromJS(v);
	        });
	      }) : config.treeMap,
	      undoStack: config.undoStack != null ? Stack(config.undoStack.map(function (v) {
	        return ContentState.fromJS(v);
	      })) : config.undoStack,
	      currentContent: ContentState.fromJS(config.currentContent)
	    })));
	  };

	  EditorState.set = function set(editorState, put) {
	    var map = editorState.getImmutable().withMutations(function (state) {
	      var existingDecorator = state.get('decorator');
	      var decorator = existingDecorator;

	      if (put.decorator === null) {
	        decorator = null;
	      } else if (put.decorator) {
	        decorator = put.decorator;
	      }

	      var newContent = put.currentContent || editorState.getCurrentContent();

	      if (decorator !== existingDecorator) {
	        var treeMap = state.get('treeMap');
	        var newTreeMap;

	        if (decorator && existingDecorator) {
	          newTreeMap = regenerateTreeForNewDecorator(newContent, newContent.getBlockMap(), treeMap, decorator, existingDecorator);
	        } else {
	          newTreeMap = generateNewTreeMap(newContent, decorator);
	        }

	        state.merge({
	          decorator: decorator,
	          treeMap: newTreeMap,
	          nativelyRenderedContent: null
	        });
	        return;
	      }

	      var existingContent = editorState.getCurrentContent();

	      if (newContent !== existingContent) {
	        state.set('treeMap', regenerateTreeForNewBlocks(editorState, newContent.getBlockMap(), newContent.getEntityMap(), decorator));
	      }

	      state.merge(put);
	    });
	    return new EditorState(map);
	  };

	  var _proto = EditorState.prototype;

	  _proto.toJS = function toJS() {
	    return this.getImmutable().toJS();
	  };

	  _proto.getAllowUndo = function getAllowUndo() {
	    return this.getImmutable().get('allowUndo');
	  };

	  _proto.getCurrentContent = function getCurrentContent() {
	    return this.getImmutable().get('currentContent');
	  };

	  _proto.getUndoStack = function getUndoStack() {
	    return this.getImmutable().get('undoStack');
	  };

	  _proto.getRedoStack = function getRedoStack() {
	    return this.getImmutable().get('redoStack');
	  };

	  _proto.getSelection = function getSelection() {
	    return this.getImmutable().get('selection');
	  };

	  _proto.getDecorator = function getDecorator() {
	    return this.getImmutable().get('decorator');
	  };

	  _proto.isInCompositionMode = function isInCompositionMode() {
	    return this.getImmutable().get('inCompositionMode');
	  };

	  _proto.mustForceSelection = function mustForceSelection() {
	    return this.getImmutable().get('forceSelection');
	  };

	  _proto.getNativelyRenderedContent = function getNativelyRenderedContent() {
	    return this.getImmutable().get('nativelyRenderedContent');
	  };

	  _proto.getLastChangeType = function getLastChangeType() {
	    return this.getImmutable().get('lastChangeType');
	  }
	  /**
	   * While editing, the user may apply inline style commands with a collapsed
	   * cursor, intending to type text that adopts the specified style. In this
	   * case, we track the specified style as an "override" that takes precedence
	   * over the inline style of the text adjacent to the cursor.
	   *
	   * If null, there is no override in place.
	   */
	  ;

	  _proto.getInlineStyleOverride = function getInlineStyleOverride() {
	    return this.getImmutable().get('inlineStyleOverride');
	  };

	  EditorState.setInlineStyleOverride = function setInlineStyleOverride(editorState, inlineStyleOverride) {
	    return EditorState.set(editorState, {
	      inlineStyleOverride: inlineStyleOverride
	    });
	  }
	  /**
	   * Get the appropriate inline style for the editor state. If an
	   * override is in place, use it. Otherwise, the current style is
	   * based on the location of the selection state.
	   */
	  ;

	  _proto.getCurrentInlineStyle = function getCurrentInlineStyle() {
	    var override = this.getInlineStyleOverride();

	    if (override != null) {
	      return override;
	    }

	    var content = this.getCurrentContent();
	    var selection = this.getSelection();

	    if (selection.isCollapsed()) {
	      return getInlineStyleForCollapsedSelection(content, selection);
	    }

	    return getInlineStyleForNonCollapsedSelection(content, selection);
	  };

	  _proto.getBlockTree = function getBlockTree(blockKey) {
	    return this.getImmutable().getIn(['treeMap', blockKey]);
	  };

	  _proto.isSelectionAtStartOfContent = function isSelectionAtStartOfContent() {
	    var firstKey = this.getCurrentContent().getBlockMap().first().getKey();
	    return this.getSelection().hasEdgeWithin(firstKey, 0, 0);
	  };

	  _proto.isSelectionAtEndOfContent = function isSelectionAtEndOfContent() {
	    var content = this.getCurrentContent();
	    var blockMap = content.getBlockMap();
	    var last = blockMap.last();
	    var end = last.getLength();
	    return this.getSelection().hasEdgeWithin(last.getKey(), end, end);
	  };

	  _proto.getDirectionMap = function getDirectionMap() {
	    return this.getImmutable().get('directionMap');
	  }
	  /**
	   * Incorporate native DOM selection changes into the EditorState. This
	   * method can be used when we simply want to accept whatever the DOM
	   * has given us to represent selection, and we do not need to re-render
	   * the editor.
	   *
	   * To forcibly move the DOM selection, see `EditorState.forceSelection`.
	   */
	  ;

	  EditorState.acceptSelection = function acceptSelection(editorState, selection) {
	    return updateSelection(editorState, selection, false);
	  }
	  /**
	   * At times, we need to force the DOM selection to be where we
	   * need it to be. This can occur when the anchor or focus nodes
	   * are non-text nodes, for instance. In this case, we want to trigger
	   * a re-render of the editor, which in turn forces selection into
	   * the correct place in the DOM. The `forceSelection` method
	   * accomplishes this.
	   *
	   * This method should be used in cases where you need to explicitly
	   * move the DOM selection from one place to another without a change
	   * in ContentState.
	   */
	  ;

	  EditorState.forceSelection = function forceSelection(editorState, selection) {
	    if (!selection.getHasFocus()) {
	      selection = selection.set('hasFocus', true);
	    }

	    return updateSelection(editorState, selection, true);
	  }
	  /**
	   * Move selection to the end of the editor without forcing focus.
	   */
	  ;

	  EditorState.moveSelectionToEnd = function moveSelectionToEnd(editorState) {
	    var content = editorState.getCurrentContent();
	    var lastBlock = content.getLastBlock();
	    var lastKey = lastBlock.getKey();
	    var length = lastBlock.getLength();
	    return EditorState.acceptSelection(editorState, new SelectionState({
	      anchorKey: lastKey,
	      anchorOffset: length,
	      focusKey: lastKey,
	      focusOffset: length,
	      isBackward: false
	    }));
	  }
	  /**
	   * Force focus to the end of the editor. This is useful in scenarios
	   * where we want to programmatically focus the input and it makes sense
	   * to allow the user to continue working seamlessly.
	   */
	  ;

	  EditorState.moveFocusToEnd = function moveFocusToEnd(editorState) {
	    var afterSelectionMove = EditorState.moveSelectionToEnd(editorState);
	    return EditorState.forceSelection(afterSelectionMove, afterSelectionMove.getSelection());
	  }
	  /**
	   * Push the current ContentState onto the undo stack if it should be
	   * considered a boundary state, and set the provided ContentState as the
	   * new current content.
	   */
	  ;

	  EditorState.push = function push(editorState, contentState, changeType) {
	    var forceSelection = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;

	    if (editorState.getCurrentContent() === contentState) {
	      return editorState;
	    }

	    var directionMap = EditorBidiService.getDirectionMap(contentState, editorState.getDirectionMap());

	    if (!editorState.getAllowUndo()) {
	      return EditorState.set(editorState, {
	        currentContent: contentState,
	        directionMap: directionMap,
	        lastChangeType: changeType,
	        selection: contentState.getSelectionAfter(),
	        forceSelection: forceSelection,
	        inlineStyleOverride: null
	      });
	    }

	    var selection = editorState.getSelection();
	    var currentContent = editorState.getCurrentContent();
	    var undoStack = editorState.getUndoStack();
	    var newContent = contentState;

	    if (selection !== currentContent.getSelectionAfter() || mustBecomeBoundary(editorState, changeType)) {
	      undoStack = undoStack.push(currentContent);
	      newContent = newContent.set('selectionBefore', selection);
	    } else if (changeType === 'insert-characters' || changeType === 'backspace-character' || changeType === 'delete-character') {
	      // Preserve the previous selection.
	      newContent = newContent.set('selectionBefore', currentContent.getSelectionBefore());
	    }

	    var inlineStyleOverride = editorState.getInlineStyleOverride(); // Don't discard inline style overrides for the following change types:

	    var overrideChangeTypes = ['adjust-depth', 'change-block-type', 'split-block'];

	    if (overrideChangeTypes.indexOf(changeType) === -1) {
	      inlineStyleOverride = null;
	    }

	    var editorStateChanges = {
	      currentContent: newContent,
	      directionMap: directionMap,
	      undoStack: undoStack,
	      redoStack: Stack(),
	      lastChangeType: changeType,
	      selection: contentState.getSelectionAfter(),
	      forceSelection: forceSelection,
	      inlineStyleOverride: inlineStyleOverride
	    };
	    return EditorState.set(editorState, editorStateChanges);
	  }
	  /**
	   * Make the top ContentState in the undo stack the new current content and
	   * push the current content onto the redo stack.
	   */
	  ;

	  EditorState.undo = function undo(editorState) {
	    if (!editorState.getAllowUndo()) {
	      return editorState;
	    }

	    var undoStack = editorState.getUndoStack();
	    var newCurrentContent = undoStack.peek();

	    if (!newCurrentContent) {
	      return editorState;
	    }

	    var currentContent = editorState.getCurrentContent();
	    var directionMap = EditorBidiService.getDirectionMap(newCurrentContent, editorState.getDirectionMap());
	    return EditorState.set(editorState, {
	      currentContent: newCurrentContent,
	      directionMap: directionMap,
	      undoStack: undoStack.shift(),
	      redoStack: editorState.getRedoStack().push(currentContent),
	      forceSelection: true,
	      inlineStyleOverride: null,
	      lastChangeType: 'undo',
	      nativelyRenderedContent: null,
	      selection: currentContent.getSelectionBefore()
	    });
	  }
	  /**
	   * Make the top ContentState in the redo stack the new current content and
	   * push the current content onto the undo stack.
	   */
	  ;

	  EditorState.redo = function redo(editorState) {
	    if (!editorState.getAllowUndo()) {
	      return editorState;
	    }

	    var redoStack = editorState.getRedoStack();
	    var newCurrentContent = redoStack.peek();

	    if (!newCurrentContent) {
	      return editorState;
	    }

	    var currentContent = editorState.getCurrentContent();
	    var directionMap = EditorBidiService.getDirectionMap(newCurrentContent, editorState.getDirectionMap());
	    return EditorState.set(editorState, {
	      currentContent: newCurrentContent,
	      directionMap: directionMap,
	      undoStack: editorState.getUndoStack().push(currentContent),
	      redoStack: redoStack.shift(),
	      forceSelection: true,
	      inlineStyleOverride: null,
	      lastChangeType: 'redo',
	      nativelyRenderedContent: null,
	      selection: newCurrentContent.getSelectionAfter()
	    });
	  }
	  /**
	   * Not for public consumption.
	   */
	  ;

	  function EditorState(immutable) {
	    _defineProperty(this, "_immutable", void 0);

	    this._immutable = immutable;
	  }
	  /**
	   * Not for public consumption.
	   */


	  _proto.getImmutable = function getImmutable() {
	    return this._immutable;
	  };

	  return EditorState;
	}();
	/**
	 * Set the supplied SelectionState as the new current selection, and set
	 * the `force` flag to trigger manual selection placement by the view.
	 */


	function updateSelection(editorState, selection, forceSelection) {
	  return EditorState.set(editorState, {
	    selection: selection,
	    forceSelection: forceSelection,
	    nativelyRenderedContent: null,
	    inlineStyleOverride: null
	  });
	}
	/**
	 * Regenerate the entire tree map for a given ContentState and decorator.
	 * Returns an OrderedMap that maps all available ContentBlock objects.
	 */


	function generateNewTreeMap(contentState, decorator) {
	  return contentState.getBlockMap().map(function (block) {
	    return BlockTree.generate(contentState, block, decorator);
	  }).toOrderedMap();
	}
	/**
	 * Regenerate tree map objects for all ContentBlocks that have changed
	 * between the current editorState and newContent. Returns an OrderedMap
	 * with only changed regenerated tree map objects.
	 */


	function regenerateTreeForNewBlocks(editorState, newBlockMap, newEntityMap, decorator) {
	  var contentState = editorState.getCurrentContent().set('entityMap', newEntityMap);
	  var prevBlockMap = contentState.getBlockMap();
	  var prevTreeMap = editorState.getImmutable().get('treeMap');
	  return prevTreeMap.merge(newBlockMap.toSeq().filter(function (block, key) {
	    return block !== prevBlockMap.get(key);
	  }).map(function (block) {
	    return BlockTree.generate(contentState, block, decorator);
	  }));
	}
	/**
	 * Generate tree map objects for a new decorator object, preserving any
	 * decorations that are unchanged from the previous decorator.
	 *
	 * Note that in order for this to perform optimally, decoration Lists for
	 * decorators should be preserved when possible to allow for direct immutable
	 * List comparison.
	 */


	function regenerateTreeForNewDecorator(content, blockMap, previousTreeMap, decorator, existingDecorator) {
	  return previousTreeMap.merge(blockMap.toSeq().filter(function (block) {
	    return decorator.getDecorations(block, content) !== existingDecorator.getDecorations(block, content);
	  }).map(function (block) {
	    return BlockTree.generate(content, block, decorator);
	  }));
	}
	/**
	 * Return whether a change should be considered a boundary state, given
	 * the previous change type. Allows us to discard potential boundary states
	 * during standard typing or deletion behavior.
	 */


	function mustBecomeBoundary(editorState, changeType) {
	  var lastChangeType = editorState.getLastChangeType();
	  return changeType !== lastChangeType || changeType !== 'insert-characters' && changeType !== 'backspace-character' && changeType !== 'delete-character';
	}

	function getInlineStyleForCollapsedSelection(content, selection) {
	  var startKey = selection.getStartKey();
	  var startOffset = selection.getStartOffset();
	  var startBlock = content.getBlockForKey(startKey); // If the cursor is not at the start of the block, look backward to
	  // preserve the style of the preceding character.

	  if (startOffset > 0) {
	    return startBlock.getInlineStyleAt(startOffset - 1);
	  } // The caret is at position zero in this block. If the block has any
	  // text at all, use the style of the first character.


	  if (startBlock.getLength()) {
	    return startBlock.getInlineStyleAt(0);
	  } // Otherwise, look upward in the document to find the closest character.


	  return lookUpwardForInlineStyle(content, startKey);
	}

	function getInlineStyleForNonCollapsedSelection(content, selection) {
	  var startKey = selection.getStartKey();
	  var startOffset = selection.getStartOffset();
	  var startBlock = content.getBlockForKey(startKey); // If there is a character just inside the selection, use its style.

	  if (startOffset < startBlock.getLength()) {
	    return startBlock.getInlineStyleAt(startOffset);
	  } // Check if the selection at the end of a non-empty block. Use the last
	  // style in the block.


	  if (startOffset > 0) {
	    return startBlock.getInlineStyleAt(startOffset - 1);
	  } // Otherwise, look upward in the document to find the closest character.


	  return lookUpwardForInlineStyle(content, startKey);
	}

	function lookUpwardForInlineStyle(content, fromKey) {
	  var lastNonEmpty = content.getBlockMap().reverse().skipUntil(function (_, k) {
	    return k === fromKey;
	  }).skip(1).skipUntil(function (block, _) {
	    return block.getLength();
	  }).first();

	  if (lastNonEmpty) {
	    return lastNonEmpty.getInlineStyleAt(lastNonEmpty.getLength() - 1);
	  }

	  return OrderedSet();
	}

	EditorState_1 = EditorState;
	return EditorState_1;
}

export { requireEditorState as __require };
//# sourceMappingURL=EditorState.js.map
