import RTEDTOClassManager from '../../../helpers/rte-manager/dto-class-manager';
import RTEDTORendererManager from '../../../helpers/rte-manager/dto-renderer-manager';
import RTEDTOActionStrategyManager from '../../../helpers/rte-manager/dto-action-strategy-manager';
import ElementToDTOClassStrategyManager from '../../../helpers/rte-manager/element-dto-class-strategy-manager';
import rteExtensionContextManager from '../helpers/extension-context-manager';
import { ActionHandleStrategyRegistry } from '../dto/action-handle-strategies/action-handle-strategy-registry';
import { VegaRTEExtensionRenderer } from './base-extension-renderer';
import { ActionHandlerInterceptorRegistry } from '../dto/action-handle-strategies/action-handle-interceptor-registry';
import { methodPlaceholder } from 'vega-slimmer/core';
import htmlElementToAnnotationGenerator from '../slimmers/controllers/helper/element-to-dto-strategy/annotation-handler/html-element-to-annotation-generator';
import { RTEFilterStylesStrategyRegistry } from '../dto/filter-styles-strategies/filter-styles-strategy-registry';
/**
 * Abstract class for Vega Rich Text Editor extensions.
 */
export class VegaRTEExtension {
  constructor() {
    /**
     * The context of the RTE extension, which may include references to the host editor and other relevant information.
     */
    this.extensionContext = null;
    this.hasCustomStylesRenderers = new Set();
  }
  /**
   * Registers an action handle strategy for a specific node or block class.
   *
   * @param {string} nodeOrBlockClassName - The name of the node or block class.
   * @param {string} actionType - The type of the action.
   * @param {ActionHandleStrategy<ModifyContentAction | AnnotationAction, RTENode | RTEBlock | VegaRTEContent>} strategy - The strategy to register.
   */
  static registerActionHandleStrategy(nodeOrBlockClassName, actionType, strategy) {
    ActionHandleStrategyRegistry.register(actionType, nodeOrBlockClassName, strategy);
  }
  /**
   * Registers an action handler interceptor for a specific node or block class.
   *
   * @param {string} nodeOrBlockClassName - The name of the node or block class.
   * @param {string} actionType - The type of the action.
   * @param {ActionHandlerInterceptor<ModifyContentAction, RTENode | RTEBlock | VegaRTEContent>} strategy - The interceptor to register.
   */
  static registerActionHandlerInterceptor(nodeOrBlockClassName, actionType, strategy) {
    ActionHandlerInterceptorRegistry.register(actionType, nodeOrBlockClassName, strategy);
  }
  /**
   * Registers a filter styles strategy for a specific block or node class.
   *
   * @param {string} blockOrNodeClassName - The name of the block or node class.
   * @param {RTEFilterStylesStrategy} strategy - The filter styles strategy to register.
   */
  static registerFilterStylesStrategy(blockOrNodeClassName, strategy) {
    RTEFilterStylesStrategyRegistry.register(blockOrNodeClassName, strategy);
  }
  /**
   * Lifecycle hook called by the rich text editor before the first render
   * (during `componentWillLoad`).  Override this method to perform per-host
   * pre-render setup — for example, registering a host-specific toolbar button
   * renderer via {@link registerToolbarButtonRenderer} so that each editor on
   * the page gets its own isolated renderer instance.
   *
   * The default implementation is a no-op; subclasses may override selectively.
   *
   * @typedef HTMLVegaRichTextEditorElement - The type of the host rich text editor element.
   * @param {HTMLVegaRichTextEditorElement} host - The host rich text editor element that is about to load.
   */
  prepareBeforeLoad(host) {
    methodPlaceholder(host);
  }
  /**
   * Initializes the RTE extension with the provided context.
   *
   * @param {RTEExtensionContext} context - The context of the RTE extension.
   */
  initialExtensionAfterLoad(context) {
    this.extensionContext = context;
    rteExtensionContextManager.setExtensionContext(context);
  }
  /**
   * Callback method invoked when the extension is destroyed.
   * Override this method to perform any necessary cleanup.
   */
  destroyExtension() {
    methodPlaceholder();
  }
  /**
   * Collect custom styles for the extension renderers.
   * If custom nodes have special styles, override this method to provide the styles.
   *
   * @returns {string} - The custom styles as a string.
   */
  collectExtensionRendererStyles() {
    let styles = '';
    if (this.hasCustomStylesRenderers.size > 0) {
      this.hasCustomStylesRenderers.forEach((renderer) => {
        styles += `${renderer.injectRTEScopeStyles()}\n`;
      });
    }
    return styles;
  }
  /**
   * Register a node type with the extension.
   *
   * @param {string} type - The type of the node or block. The type should be a string that uniquely identifies the node or block.
   * @param {ClassType<RTEBlock | RTENode>} DTOClass - The DTO class to register.
   */
  registerNode(type, DTOClass) {
    RTEDTOClassManager.registerRTEDTOClass(type, DTOClass);
  }
  /**
   * Register a renderer for a node type with the extension.
   *
   * @param {string} type - The type of the node or block. The type should be a string that uniquely identifies the node or block.
   * @param {BaseRenderer} renderer - The renderer to register.
   */
  registerRenderer(type, renderer) {
    RTEDTORendererManager.registerRTEDTORenderer(type, renderer);
    if (renderer instanceof VegaRTEExtensionRenderer && renderer.injectRTEScopeStyles()) {
      this.hasCustomStylesRenderers.add(renderer);
    }
  }
  /**
   * Register a toolbar button renderer for the extension.
   * When a `host` element is provided the renderer is registered in the per-host map
   * (via {@link RTEDTORendererManager#registerRTEToolbarButtonRendererForHost}), giving
   * that host an isolated renderer instance that takes precedence over the global singleton.
   * Omit `host` to fall back to the global registration (backwards-compatible default).
   *
   * @param {string} type - The type of the toolbar button.
   * @param {VegaRTEToolbarButtonRenderer} renderer - The renderer to register.
   * @param {HTMLVegaRichTextEditorElement} [host] - Optional host element for per-host isolation.
   */
  registerToolbarButtonRenderer(type, renderer, host) {
    if (host) {
      RTEDTORendererManager.registerRTEToolbarButtonRendererForHost(host, type, renderer);
    }
    else {
      RTEDTORendererManager.registerRTEToolbarButtonRenderer(type, renderer);
    }
  }
  /**
   * This is a helper method that utilizes RTEUtils to register common strategies.
   * Call the method with the class name of the block to make it support basic strategies like:
   * - Delete children
   * - Append the children
   * - Delete the block children content
   *
   * @param {string} blockClassName - The class name of the block to register strategies for.
   */
  registerBlockBasicStrategies(blockClassName) {
    RTEDTOActionStrategyManager.registerBlockBasicStrategies(blockClassName);
  }
  /**
   * Unregister a strategy for a specific action type and block class if not need.
   *
   * @param {string} actionType - The special action type or the action class name.
   * @param {string} blockClassName - The class name of the block to unregister the strategy for.
   */
  unRegisterStrategy(actionType, blockClassName) {
    ActionHandleStrategyRegistry.unregister(actionType, blockClassName);
  }
  /**
   * Unregister a strategy for a specific action type and block class if not need.
   *
   * @param {string} actionType - The special action type or the action class name.
   * @param {string} blockClassName - The class name of the block to unregister the strategy for.
   * @param {ActionHandlerInterceptor<ModifyContentAction, RTENode | RTEBlock | VegaRTEContent>} strategy - The interceptor to unregister.
   */
  unRegisterInterceptor(actionType, blockClassName, strategy) {
    ActionHandlerInterceptorRegistry.unregister(actionType, blockClassName, strategy);
  }
  /**
   * Register an element to block DTO class strategy.
   *
   * @param {ElementToDTOStrategy} strategy - The strategy to register.
   */
  registerElementToBlockDTOClassStrategy(strategy) {
    ElementToDTOClassStrategyManager.registerElementToBlockStrategy(strategy);
  }
  /**
   * Register an element to node DTO class strategy.
   *
   * @param {ElementToDTOStrategy} strategy - The strategy to register.
   */
  registerElementToNodeDTOClassStrategy(strategy) {
    ElementToDTOClassStrategyManager.registerElementToNodeStrategy(strategy);
  }
  /**
   * Get the registered element to node DTO class strategies.
   *
   * @returns {ElementToDTOStrategy[]} - The registered element to node DTO class strategies.
   */
  getElementToNodeDTOClassStrategies() {
    return ElementToDTOClassStrategyManager.getElementToNodeStrategies();
  }
  /**
   * Register a custom annotation handler for HTML to DTO conversion.
   *
   * @param {AnnotationGeneratorStrategyAbstract} handler - The annotation handler to register.
   */
  registerAnnotationHandler(handler) {
    htmlElementToAnnotationGenerator.registerHandler(handler);
  }
}
