import { h } from '@stencil/core';
import { InternalAnnotationTypeEnum } from '../../annotations/annotation.abstract';
import { RTEBlockRenderer } from './block-renderer.abstract';
import RTELinkWrapperRenderer from './link-wrapper-renderer';
import RTEDTORendererManager from '../../../../../helpers/rte-manager/dto-renderer-manager';
import RTETextNodeRenderer from '../nodes/text-node-renderer';
/**
 * Abstract class for rendering blocks that contain text nodes with support for rendering text with link styles.
 */
export class RTEBlockTextNodesRenderer extends RTEBlockRenderer {
  /**
   * Renders the text nodes of the block(RTETextBlock, RTEListItemBlock), applying link group annotation rendering if present.
   *
   * @param {RTETextBlock} block - The text block containing nodes to render.
   * @param {RTERenderContext} renderContext - The context for rendering.
   * @returns {(HTMLElement | VNode)[]} An array of rendered HTMLElements.
   */
  renderNodes(block, renderContext) {
    const linkGroupAnnotation = block.getAnnotationByType(InternalAnnotationTypeEnum.LINK_GROUP);
    return linkGroupAnnotation
      ? RTELinkWrapperRenderer.render(block.children, linkGroupAnnotation, renderContext)
      : this.renderGroupedNodesAtDepth(block.children, 0, renderContext);
  }
  /**
   * Recursively groups `nodes` by their inline HTML wrapper `groupId` at the given
   * `depth`, emitting a single shared wrapper element for adjacent siblings and
   * descending into the next depth for each group.  Nodes without a `groupId` at
   * the current depth are rendered individually (same as the non-grouped path).
   *
   * @param {RTETextNode[]} nodes - The nodes to render.
   * @param {number} depth - Current depth in the inline HTML chain (0 = outermost).
   * @param {RTERenderContext} renderContext - The render context.
   * @returns {(HTMLElement | VNode)[]} Rendered nodes/elements at this depth.
   */
  renderGroupedNodesAtDepth(nodes, depth, renderContext) {
    var _a;
    const result = [];
    let i = 0;
    while (i < nodes.length) {
      const tag = nodes[i].getInlineHtmlTagAtDepth(depth);
      if (!(tag === null || tag === void 0 ? void 0 : tag.groupId)) {
        result.push(this.renderNodeFromDepth(nodes[i], depth, renderContext));
        i++;
        continue;
      }
      let groupEnd = i + 1;
      while (groupEnd < nodes.length &&
        ((_a = nodes[groupEnd].getInlineHtmlTagAtDepth(depth)) === null || _a === void 0 ? void 0 : _a.groupId) === tag.groupId) {
        groupEnd++;
      }
      if (groupEnd === i + 1) {
        // Single node in group — render normally from this depth.
        result.push(this.renderNodeFromDepth(nodes[i], depth, renderContext));
      }
      else {
        // Multiple nodes share a wrapper — emit the wrapper once and recurse.
        const attrs = tag.annotation.renderProps();
        const inner = this.renderGroupedNodesAtDepth(nodes.slice(i, groupEnd), depth + 1, renderContext);
        result.push(h(tag.htmlTag, attrs, inner));
      }
      i = groupEnd;
    }
    return result;
  }
  /**
   * Renders a single node starting from the given inline HTML depth.
   * At depth 0 the full annotation chain is rendered normally.
   * At depth > 0 the chain begins at that depth (the outer wrappers have
   * already been emitted by the grouping logic above).
   *
   * @param {RTETextNode} node - The node to render.
   * @param {number} depth - Depth in the inline HTML chain to start from.
   * @param {RTERenderContext} renderContext - The render context.
   * @returns {HTMLElement | VNode} The rendered node.
   */
  renderNodeFromDepth(node, depth, renderContext) {
    if (depth === 0) {
      const nodeRenderer = RTEDTORendererManager.getRTERenderer(node.type);
      return nodeRenderer.render(node, renderContext, h);
    }
    return RTETextNodeRenderer.renderFromAnnotation(node, node.getInlineHtmlAnnotationAtDepth(depth));
  }
}
