import changeManager from '../../../../../../helpers/change-manager/change-manager';
import domNodeSubjectFactory from '../../../../../../helpers/change-manager/subject/dom-node-subject/dom-node-subject-factory';
import { VegaInternalRichTextEditDeleteSelectedNodes } from '../../../../../../helpers/event-manager/event-id/vega-internal-event-id';
import { generateUUID } from '../../../../../../utils/misc';
import { AppendChildrenAction } from '../../../../dto/actions/append-child-nodes-action';
import { RTETextBlock } from '../../../../dto/blocks/text-block';
import { RTETextNode } from '../../../../dto/nodes/text-node';
const ROOT_CONTAINER_CLASS_NAME = 'rich-text-content';
/** This code snippet is defining an abstract class named `BaseHandler` with an abstract method `execute`. */
export class BaseHandler {
  /**
   * The function `execute` initializes the current state and selection, and then handles an event if provided.
   *
   * @param {VegaRTEContent} currentState - The current state of the VegaRTE content.
   * @param {SelectionController} selectionController - Manages the selection of items in the user interface.
   * @param {HTMLElement} richTextEditor - The current rich text editor component
   * @param {InputEvent} [event] - It is used to pass an input event to the method for handling.
   */
  execute(currentState, selectionController, richTextEditor, event) {
    this.initCurrentStateAndSelection(currentState, selectionController);
    this.setCurrentRichTextEditor(richTextEditor);
    this.handleEvent(event);
  }
  /**
   * The function `isRootContainer` checks if an HTML element is a root container with a class of 'rich-text-content'.
   *
   * @param {HTMLElement} element - HTMLElement
   * @returns {boolean} The boolean value
   */
  isRootContainer(element) {
    return (element &&
      element.nodeType === Node.ELEMENT_NODE &&
      element.classList.contains(ROOT_CONTAINER_CLASS_NAME));
  }
  /**
   * Checks if a given HTML element represents an empty paragraph containing only a line break element.
   *
   * @param {HTMLElement} node - An HTMLElement node that represents a paragraph element in the HTML document.
   * @returns {boolean} boolean result
   */
  isEmptyParagraph(node) {
    return node && node.childNodes && node.childNodes.length === 0;
  }
  /**
   * Removes selected nodes within a range in a rich text editor content.
   * The method is only used for different nodes are selected
   *
   * @param {boolean} [mergeNode] Merge start node and end node or not, default value is false.
   * @returns {RTENode} The range start node, usually the start node is the first item of selectedNodes, if the selectedNodes is all removed, the start node will be a new text node.
   */
  removeSelectionRange(mergeNode = false) {
    changeManager.notify(domNodeSubjectFactory.getSubject(this.richTextEditorRef, VegaInternalRichTextEditDeleteSelectedNodes), { host: this.richTextEditorRef, detail: mergeNode });
    const range = this.selectionController.getCurrentRange();
    const selectedNodes = this.selectionController.getSelectedNodes();
    return range.startNode || selectedNodes[0];
  }
  /**
   * Creates a new paragraph with an empty text node and returns it.
   *
   * @returns {RTETextBlock} An empty paragraph with a unique identifier and a text node appended to it.
   */
  createEmptyParagraph() {
    const paragraph = new RTETextBlock(generateUUID(), 'paragraph');
    const textNode = new RTETextNode(`${paragraph.id}1`, '', paragraph);
    paragraph.apply(new AppendChildrenAction([textNode]));
    return paragraph;
  }
  /**
   * The function initializes the current state and selection controller in TypeScript.
   *
   * @param {VegaRTEContent} currentState - The current state of a Vega runtime environment content.
   * @param {SelectionController} selectionController - It is used to manage the selection of content within the VegaRTE editor.
   */
  initCurrentStateAndSelection(currentState, selectionController) {
    this.currentState = currentState;
    this.selectionController = selectionController;
  }
  /**
   * Queries the rich text editor element from the input event target.
   *
   * @param {HTMLElement} richTextEditor - The current rich text editor component
   */
  setCurrentRichTextEditor(richTextEditor) {
    this.richTextEditorRef = richTextEditor;
  }
}
