import { RTENode } from '../../../../dto/nodes/node.abstract';
import { BaseHandler } from './base-handler';
import { SplitBlockWithNodeAction } from '../../../../dto/actions/split-block-with-node-action';
import { MergeTwoBlocksNodesAction } from '../../../../dto/actions/merge-two-blocks-nodes-action';
import { InsertNewParagraphAction } from '../../../../dto/actions/insert-new-paragraph-action';
/** Insert a paragraph in a rich text editor based on the current selection and event. User type enter will trigger this callback */
export class InsertParagraphHandler extends BaseHandler {
  /**
   * Create new paragraph node and add node to state value
   */
  handleEvent() {
    const selectedBlocks = this.selectionController.getSelectedBlocks();
    if (selectedBlocks.length) {
      if (selectedBlocks.length < 2) {
        this.breakSingleBlock();
      }
      else {
        this.breakMultipleBlocks();
      }
    }
  }
  /**
   * Handles breaking blocks in an RTE editor based on the current selection and position.
   */
  breakMultipleBlocks() {
    const selectedBlocks = this.selectionController.getSelectedBlocks();
    const range = this.selectionController.getCurrentRange();
    const cursorNode = this.removeSelectionRange();
    // If the start or end block contains a list item block, it needs to be processed separately
    if ((selectedBlocks.length && selectedBlocks[0].type === 'list-item') ||
      selectedBlocks[selectedBlocks.length - 1].type === 'list-item') {
      const firstBlock = cursorNode.parent;
      const lastBlock = selectedBlocks[selectedBlocks.length - 1];
      /**
       * First block is list item
       * --before--
       * ul
       *  - li
       * p
       *  - span
       * --after--
       * ul
       *  - li
       *  - li
       */
      /**
       * End block is list item
       * --before--
       * p
       *  - span
       * ul
       *  - li
       * --after--
       * p
       *  - span
       * p
       *  - span
       */
      if (firstBlock.type !== lastBlock.type &&
        range.startContainer.nodeType === range.endContainer.nodeType) {
        firstBlock.apply(new MergeTwoBlocksNodesAction(lastBlock));
        const splitAction = new SplitBlockWithNodeAction(cursorNode, cursorNode['text'].length);
        firstBlock.apply(splitAction);
        this.switchCaretPositionToNextElement(splitAction.newBlock);
        return;
      }
    }
    this.selectionController.enqueueSelectionRangeFutureState(cursorNode, range.startOffset);
  }
  /**
   * Handles breaking a single block in an RTE editor based on the current selection and position.
   */
  breakSingleBlock() {
    const cursorNode = this.removeSelectionRange();
    const currentBlock = cursorNode instanceof RTENode ? cursorNode.parent : cursorNode;
    const { startOffset } = this.selectionController.getCurrentRange();
    if (currentBlock) {
      const breakAction = new InsertNewParagraphAction(cursorNode, startOffset);
      currentBlock.apply(breakAction);
      this.switchCaretPositionToNextElement(breakAction.newBlock);
    }
  }
  /**
   * Moves the caret to the next block element in a rich text editor.
   *
   * @param {RTEBlock} newBlock - Represents a new create block element in a rich text editor.
   */
  switchCaretPositionToNextElement(newBlock) {
    if (newBlock && newBlock.children) {
      this.selectionController.enqueueSelectionRangeFutureState(newBlock.children[0], 0);
    }
  }
}
