import changeManager from '../../../../../helpers/change-manager/change-manager';
import domNodeSubjectFactory from '../../../../../helpers/change-manager/subject/dom-node-subject/dom-node-subject-factory';
import { VegaInternalRichTextEditorSelectionRangeChange } from '../../../../../helpers/event-manager/event-id/vega-internal-event-id';
import { generateUUID } from '../../../../../utils/misc';
import stateEntityRenderingRegistry from '../../../slimmers/controllers/state-entity-rendering-registry';
import { AppendChildrenAction } from '../../actions/append-child-nodes-action';
import { RemoveChildrenAction } from '../../actions/remove-child-action';
import { RTETextBlock } from '../../blocks/text-block';
import { BlockDeleteNodeContentStrategy } from './block-delete-node-content-strategy';
/**
 * Remove the code block from the value, call this action if want to flush value after action.
 */
export class CodeBlockRemoveSelfStrategy extends BlockDeleteNodeContentStrategy {
  /**
   * @inheritDoc
   */
  handleAction(_action, target) {
    const node = target.children[0];
    const parent = target.parent;
    if (parent) {
      let focusNode = this.getPreviousNode(node);
      let offset = this.getRTENodeEndOffset(focusNode);
      if (!focusNode) {
        focusNode = this.getNextNode(node);
        offset = 0;
      }
      parent.apply(new RemoveChildrenAction(target));
      const focusElement = focusNode
        ? stateEntityRenderingRegistry.getDOMByEntity(focusNode)
        : null;
      if (parent.children.length === 0) {
        const defaultParagraph = RTETextBlock.from({
          id: generateUUID(),
          type: 'paragraph',
          nodes: [{ id: generateUUID(), type: 'text', text: '' }],
        });
        target.parent.apply(new AppendChildrenAction([defaultParagraph]));
        focusNode = defaultParagraph.children[0];
        offset = 0;
      }
      this.notifyUpdateSelection(focusNode, focusElement, offset, target);
    }
  }
  /**
   * Update the rich text next selection range.
   *
   * @param {RTENode} focusNode - The next focus node dto.
   * @param {Nullable<HTMLElement>} focusElement - The next focus element. The update selection task could run directly when the element is exist.
   * @param {number} offset - The next focus text offset.
   * @param {RTECodeBlock} target - The code block dto.
   */
  notifyUpdateSelection(focusNode, focusElement, offset, target) {
    const targetDom = stateEntityRenderingRegistry.getDOMByEntity(target);
    if (targetDom) {
      const nodeSubject = domNodeSubjectFactory.getSubjectFromParentNodeByEventId(targetDom, VegaInternalRichTextEditorSelectionRangeChange);
      if (nodeSubject) {
        changeManager.notify(nodeSubject, {
          node: focusNode,
          updateDirectly: focusElement ? true : false,
          offset,
        });
      }
    }
  }
  /**
   * Get the node content end offset.
   *
   * @param {Nullable<RTENode>} node - The RTENode.
   * @returns {number} - The number value.
   */
  getRTENodeEndOffset(node) {
    if (node) {
      return node.getRangeEndOffset();
    }
    return 0;
  }
}
