import RTEDTORendererManager from '../../../helpers/rte-manager/dto-renderer-manager';
import rteExtensionContextManager from '../helpers/extension-context-manager';
import { isNonNullable } from '../../../types/type-guard';
import { VegaRTEBaseRenderer } from '../dto/renderers/base-renderer';
import stateEntityRenderingRegistry from '../slimmers/controllers/state-entity-rendering-registry';
/**
 * Base renderer for Vega Rich Text Editor.
 */
export class VegaRTEExtensionRenderer extends VegaRTEBaseRenderer {
  /**
   * Returns the styles to be injected into the RTE scope.
   * Override this method to provide custom styles for the custom blocks or nodes.
   *
   * @returns {string} - The styles as a string.
   */
  injectRTEScopeStyles() {
    return '';
  }
  /**
   * Renders the given data as a DOM element.
   *
   * @param {RTEBlock | RTENode} renderData - The data to render, which can be a block or a node.
   * @param {RTERenderContext} rteContext - The rte editor context.
   * @param {VegaRTECreateElementFunction} createElement - The function to create a DOM element.
   * @returns {VegaRTERenderResult} - The rendered DOM element.
   */
  render(renderData, rteContext, createElement) {
    var _a;
    const element = this.doRender(createElement, renderData, rteContext);
    this.fallbackRegisterRef(element, renderData);
    this.appendChildren(((_a = element.childrenContainerGetter) === null || _a === void 0 ? void 0 : _a.call(element)) || element, renderData, rteContext, createElement);
    return element;
  }
  /**
   * Register the reference of the element in the rendering registry.
   *
   * @param {RTEBlock | RTENode} renderData - The data to register with the element.
   * @returns {VegaRTEUseRef} - The function to register the element.
   */
  useRef(renderData) {
    renderData[VegaRTEExtensionRenderer.REGISTER_REF_FLAG] = true;
    return function (element) {
      if (element) {
        stateEntityRenderingRegistry.register(element, renderData);
      }
    };
  }
  /**
   * Get a registered renderer by its key.
   *
   * @param {string} key - The key of the renderer.
   * @returns {Nullable<BaseRenderer>} - The registered renderer or null if not found.
   */
  getDTORenderer(key) {
    return RTEDTORendererManager.getRTERenderer(key);
  }
  /**
   * Get the extension context for the given rich text editor host element.
   *
   * @typedef HTMLVegaRichTextEditorElement - The type definition for the rich text editor host element.
   * @param {HTMLVegaRichTextEditorElement} el - The host rich text editor element.
   * @returns {Nullable<RTEExtensionContext>} - The extension context associated with the host.
   */
  getExtensionContext(el) {
    return rteExtensionContextManager.getExtensionContext(el);
  }
  /**
   * Auto render the block children if the block element is not exist
   *
   * @param {VegaRTERenderResult} parentElement - The parent element to append children to.
   * @param {RTEBlock | RTENode} renderData - The data to render children for.
   * @param {RTERenderContext} rteContext - The render context.
   * @param {VegaRTECreateElementFunction} createElement - The function to create a DOM element.
   */
  appendChildren(parentElement, renderData, rteContext, createElement) {
    if (Array.isArray(renderData['children']) &&
      renderData['children'].length &&
      !parentElement['$children$']) {
      parentElement['$children$'] = renderData['children']
        .map((child) => {
        return this.renderChildren(child, rteContext, createElement);
      })
        .filter(isNonNullable);
    }
  }
  /**
   * Render the children node.
   *
   * @param {RTENode | RTEBlock} renderData - The node to render children for.
   * @param {RTERenderContext} rteContext - The render context.
   * @param {VegaRTECreateElementFunction} createElement - The function to create a DOM element.
   * @returns {Nullable<VegaRTERenderResult>} - The rendered DOM element.
   */
  renderChildren(renderData, rteContext, createElement) {
    const renderer = this.getDTORenderer(renderData.type);
    if (renderer) {
      return renderer.render(renderData, rteContext, createElement);
    }
  }
  /**
   * Fallback register reference for the element.
   *
   * @param {VegaRTERenderResult} element - The rendered DOM element.
   * @param {RTEBlock | RTENode} renderData - The data to register with the element.
   */
  fallbackRegisterRef(element, renderData) {
    if (!renderData[VegaRTEExtensionRenderer.REGISTER_REF_FLAG] &&
      element['$attrs$'] &&
      !element['$attrs$']['ref']) {
      // eslint-disable-next-line jsdoc/require-jsdoc
      element['$attrs$']['ref'] = this.useRef(renderData);
    }
  }
}
VegaRTEExtensionRenderer.REGISTER_REF_FLAG = '__registeredRef__';
