import { __require as requireContentBlockNode } from './ContentBlockNode.js';
import { __require as requireGetNextDelimiterBlockKey } from './getNextDelimiterBlockKey.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 removeRangeFromContentState_1;
var hasRequiredRemoveRangeFromContentState;

function requireRemoveRangeFromContentState () {
	if (hasRequiredRemoveRangeFromContentState) return removeRangeFromContentState_1;
	hasRequiredRemoveRangeFromContentState = 1;

	var ContentBlockNode = requireContentBlockNode();

	var getNextDelimiterBlockKey = requireGetNextDelimiterBlockKey();

	var Immutable = requireImmutable();

	Immutable.List;
	    var Map = Immutable.Map;

	var transformBlock = function transformBlock(key, blockMap, func) {
	  if (!key) {
	    return;
	  }

	  var block = blockMap.get(key);

	  if (!block) {
	    return;
	  }

	  blockMap.set(key, func(block));
	};
	/**
	 * Ancestors needs to be preserved when there are non selected
	 * children to make sure we do not leave any orphans behind
	 */


	var getAncestorsKeys = function getAncestorsKeys(blockKey, blockMap) {
	  var parents = [];

	  if (!blockKey) {
	    return parents;
	  }

	  var blockNode = blockMap.get(blockKey);

	  while (blockNode && blockNode.getParentKey()) {
	    var parentKey = blockNode.getParentKey();

	    if (parentKey) {
	      parents.push(parentKey);
	    }

	    blockNode = parentKey ? blockMap.get(parentKey) : null;
	  }

	  return parents;
	};
	/**
	 * Get all next delimiter keys until we hit a root delimiter and return
	 * an array of key references
	 */


	var getNextDelimitersBlockKeys = function getNextDelimitersBlockKeys(block, blockMap) {
	  var nextDelimiters = [];

	  if (!block) {
	    return nextDelimiters;
	  }

	  var nextDelimiter = getNextDelimiterBlockKey(block, blockMap);

	  while (nextDelimiter && blockMap.get(nextDelimiter)) {
	    var _block = blockMap.get(nextDelimiter);

	    nextDelimiters.push(nextDelimiter); // we do not need to keep checking all root node siblings, just the first occurance

	    nextDelimiter = _block.getParentKey() ? getNextDelimiterBlockKey(_block, blockMap) : null;
	  }

	  return nextDelimiters;
	};

	var getNextValidSibling = function getNextValidSibling(block, blockMap, originalBlockMap) {
	  if (!block) {
	    return null;
	  } // note that we need to make sure we refer to the original block since this
	  // function is called within a withMutations


	  var nextValidSiblingKey = originalBlockMap.get(block.getKey()).getNextSiblingKey();

	  while (nextValidSiblingKey && !blockMap.get(nextValidSiblingKey)) {
	    nextValidSiblingKey = originalBlockMap.get(nextValidSiblingKey).getNextSiblingKey() || null;
	  }

	  return nextValidSiblingKey;
	};

	var getPrevValidSibling = function getPrevValidSibling(block, blockMap, originalBlockMap) {
	  if (!block) {
	    return null;
	  } // note that we need to make sure we refer to the original block since this
	  // function is called within a withMutations


	  var prevValidSiblingKey = originalBlockMap.get(block.getKey()).getPrevSiblingKey();

	  while (prevValidSiblingKey && !blockMap.get(prevValidSiblingKey)) {
	    prevValidSiblingKey = originalBlockMap.get(prevValidSiblingKey).getPrevSiblingKey() || null;
	  }

	  return prevValidSiblingKey;
	};

	var updateBlockMapLinks = function updateBlockMapLinks(blockMap, startBlock, endBlock, originalBlockMap) {
	  return blockMap.withMutations(function (blocks) {
	    // update start block if its retained
	    transformBlock(startBlock.getKey(), blocks, function (block) {
	      return block.merge({
	        nextSibling: getNextValidSibling(block, blocks, originalBlockMap),
	        prevSibling: getPrevValidSibling(block, blocks, originalBlockMap)
	      });
	    }); // update endblock if its retained

	    transformBlock(endBlock.getKey(), blocks, function (block) {
	      return block.merge({
	        nextSibling: getNextValidSibling(block, blocks, originalBlockMap),
	        prevSibling: getPrevValidSibling(block, blocks, originalBlockMap)
	      });
	    }); // update start block parent ancestors

	    getAncestorsKeys(startBlock.getKey(), originalBlockMap).forEach(function (parentKey) {
	      return transformBlock(parentKey, blocks, function (block) {
	        return block.merge({
	          children: block.getChildKeys().filter(function (key) {
	            return blocks.get(key);
	          }),
	          nextSibling: getNextValidSibling(block, blocks, originalBlockMap),
	          prevSibling: getPrevValidSibling(block, blocks, originalBlockMap)
	        });
	      });
	    }); // update start block next - can only happen if startBlock == endBlock

	    transformBlock(startBlock.getNextSiblingKey(), blocks, function (block) {
	      return block.merge({
	        prevSibling: startBlock.getPrevSiblingKey()
	      });
	    }); // update start block prev

	    transformBlock(startBlock.getPrevSiblingKey(), blocks, function (block) {
	      return block.merge({
	        nextSibling: getNextValidSibling(block, blocks, originalBlockMap)
	      });
	    }); // update end block next

	    transformBlock(endBlock.getNextSiblingKey(), blocks, function (block) {
	      return block.merge({
	        prevSibling: getPrevValidSibling(block, blocks, originalBlockMap)
	      });
	    }); // update end block prev

	    transformBlock(endBlock.getPrevSiblingKey(), blocks, function (block) {
	      return block.merge({
	        nextSibling: endBlock.getNextSiblingKey()
	      });
	    }); // update end block parent ancestors

	    getAncestorsKeys(endBlock.getKey(), originalBlockMap).forEach(function (parentKey) {
	      transformBlock(parentKey, blocks, function (block) {
	        return block.merge({
	          children: block.getChildKeys().filter(function (key) {
	            return blocks.get(key);
	          }),
	          nextSibling: getNextValidSibling(block, blocks, originalBlockMap),
	          prevSibling: getPrevValidSibling(block, blocks, originalBlockMap)
	        });
	      });
	    }); // update next delimiters all the way to a root delimiter

	    getNextDelimitersBlockKeys(endBlock, originalBlockMap).forEach(function (delimiterKey) {
	      return transformBlock(delimiterKey, blocks, function (block) {
	        return block.merge({
	          nextSibling: getNextValidSibling(block, blocks, originalBlockMap),
	          prevSibling: getPrevValidSibling(block, blocks, originalBlockMap)
	        });
	      });
	    }); // if parent (startBlock) was deleted

	    if (blockMap.get(startBlock.getKey()) == null && blockMap.get(endBlock.getKey()) != null && endBlock.getParentKey() === startBlock.getKey() && endBlock.getPrevSiblingKey() == null) {
	      var prevSiblingKey = startBlock.getPrevSiblingKey(); // endBlock becomes next sibling of parent's prevSibling

	      transformBlock(endBlock.getKey(), blocks, function (block) {
	        return block.merge({
	          prevSibling: prevSiblingKey
	        });
	      });
	      transformBlock(prevSiblingKey, blocks, function (block) {
	        return block.merge({
	          nextSibling: endBlock.getKey()
	        });
	      }); // Update parent for previous parent's children, and children for that parent

	      var prevSibling = prevSiblingKey ? blockMap.get(prevSiblingKey) : null;
	      var newParentKey = prevSibling ? prevSibling.getParentKey() : null;
	      startBlock.getChildKeys().forEach(function (childKey) {
	        transformBlock(childKey, blocks, function (block) {
	          return block.merge({
	            parent: newParentKey // set to null if there is no parent

	          });
	        });
	      });

	      if (newParentKey != null) {
	        var newParent = blockMap.get(newParentKey);
	        transformBlock(newParentKey, blocks, function (block) {
	          return block.merge({
	            children: newParent.getChildKeys().concat(startBlock.getChildKeys())
	          });
	        });
	      } // last child of deleted parent should point to next sibling


	      transformBlock(startBlock.getChildKeys().find(function (key) {
	        var block = blockMap.get(key);
	        return block.getNextSiblingKey() === null;
	      }), blocks, function (block) {
	        return block.merge({
	          nextSibling: startBlock.getNextSiblingKey()
	        });
	      });
	    }
	  });
	};

	var removeRangeFromContentState = function removeRangeFromContentState(contentState, selectionState) {
	  if (selectionState.isCollapsed()) {
	    return contentState;
	  }

	  var blockMap = contentState.getBlockMap();
	  var startKey = selectionState.getStartKey();
	  var startOffset = selectionState.getStartOffset();
	  var endKey = selectionState.getEndKey();
	  var endOffset = selectionState.getEndOffset();
	  var startBlock = blockMap.get(startKey);
	  var endBlock = blockMap.get(endKey); // we assume that ContentBlockNode and ContentBlocks are not mixed together

	  var isExperimentalTreeBlock = startBlock instanceof ContentBlockNode; // used to retain blocks that should not be deleted to avoid orphan children

	  var parentAncestors = [];

	  if (isExperimentalTreeBlock) {
	    var endBlockchildrenKeys = endBlock.getChildKeys();
	    var endBlockAncestors = getAncestorsKeys(endKey, blockMap); // endBlock has unselected siblings so we can not remove its ancestors parents

	    if (endBlock.getNextSiblingKey()) {
	      parentAncestors = parentAncestors.concat(endBlockAncestors);
	    } // endBlock has children so can not remove this block or any of its ancestors


	    if (!endBlockchildrenKeys.isEmpty()) {
	      parentAncestors = parentAncestors.concat(endBlockAncestors.concat([endKey]));
	    } // we need to retain all ancestors of the next delimiter block


	    parentAncestors = parentAncestors.concat(getAncestorsKeys(getNextDelimiterBlockKey(endBlock, blockMap), blockMap));
	  }

	  var characterList;

	  if (startBlock === endBlock) {
	    characterList = removeFromList(startBlock.getCharacterList(), startOffset, endOffset);
	  } else {
	    characterList = startBlock.getCharacterList().slice(0, startOffset).concat(endBlock.getCharacterList().slice(endOffset));
	  }

	  var modifiedStart = startBlock.merge({
	    text: startBlock.getText().slice(0, startOffset) + endBlock.getText().slice(endOffset),
	    characterList: characterList
	  }); // If cursor (collapsed) is at the start of the first child, delete parent
	  // instead of child

	  var shouldDeleteParent = isExperimentalTreeBlock && startOffset === 0 && endOffset === 0 && endBlock.getParentKey() === startKey && endBlock.getPrevSiblingKey() == null;
	  var newBlocks = shouldDeleteParent ? Map([[startKey, null]]) : blockMap.toSeq().skipUntil(function (_, k) {
	    return k === startKey;
	  }).takeUntil(function (_, k) {
	    return k === endKey;
	  }).filter(function (_, k) {
	    return parentAncestors.indexOf(k) === -1;
	  }).concat(Map([[endKey, null]])).map(function (_, k) {
	    return k === startKey ? modifiedStart : null;
	  });
	  var updatedBlockMap = blockMap.merge(newBlocks).filter(function (block) {
	    return !!block;
	  }); // Only update tree block pointers if the range is across blocks

	  if (isExperimentalTreeBlock && startBlock !== endBlock) {
	    updatedBlockMap = updateBlockMapLinks(updatedBlockMap, startBlock, endBlock, blockMap);
	  }

	  return contentState.merge({
	    blockMap: updatedBlockMap,
	    selectionBefore: selectionState,
	    selectionAfter: selectionState.merge({
	      anchorKey: startKey,
	      anchorOffset: startOffset,
	      focusKey: startKey,
	      focusOffset: startOffset,
	      isBackward: false
	    })
	  });
	};
	/**
	 * Maintain persistence for target list when removing characters on the
	 * head and tail of the character list.
	 */


	var removeFromList = function removeFromList(targetList, startOffset, endOffset) {
	  if (startOffset === 0) {
	    while (startOffset < endOffset) {
	      targetList = targetList.shift();
	      startOffset++;
	    }
	  } else if (endOffset === targetList.count()) {
	    while (endOffset > startOffset) {
	      targetList = targetList.pop();
	      endOffset--;
	    }
	  } else {
	    var head = targetList.slice(0, startOffset);
	    var tail = targetList.slice(endOffset);
	    targetList = head.concat(tail).toList();
	  }

	  return targetList;
	};

	removeRangeFromContentState_1 = removeRangeFromContentState;
	return removeRangeFromContentState_1;
}

export { requireRemoveRangeFromContentState as __require };
//# sourceMappingURL=removeRangeFromContentState.js.map
