import { ElementToDTOStrategyOutput } from './element-to-dto-strategy.abstract';
import ElementToDTOClassStrategyManager from '../../../../../../helpers/rte-manager/element-dto-class-strategy-manager';
/** Element to DTO processor */
class ElementToDtoStrategyProcessor {
  /**
   * Transform process.
   *
   * @param {HTMLElement[]} elements - Current elements.
   * @param {VegaRTETransformOptions} [options] - Options for transformation.
   * @returns {ElementToDTOStrategyOutput[]} - outputs.
   */
  process(elements, options = { autoMatchFormat: true, skipCustomAnnotations: true }) {
    const strategies = this.getElementToBlockStrategies();
    const outputs = [];
    for (let i = 0; i < elements.length; i++) {
      if (this.isInvalidElement(elements[i], options))
        continue;
      let canHandledCount = 0;
      for (const strategy of strategies) {
        canHandledCount = strategy.canHandle(elements, i, options);
        if (canHandledCount > 0) {
          const handledElements = elements.slice(i, i + canHandledCount);
          const output = new ElementToDTOStrategyOutput(strategy, handledElements);
          if (canHandledCount === 1 && strategy.shouldProceedToElementChildren()) {
            output.setChildrenOutput(this.process(Array.from(handledElements[0].childNodes), options));
          }
          outputs.push(output);
          i += canHandledCount - 1;
          break;
        }
      }
      if (canHandledCount === 0 && i < elements.length) {
        const elementChildren = Array.from(elements[i].childNodes);
        const childrenOutputs = this.process(Array.from(elementChildren), options);
        if (childrenOutputs.length > 0) {
          outputs.push(...childrenOutputs);
        }
      }
    }
    return outputs;
  }
  /**
   * Checks if the given element should be skipped during processing.
   *
   * Comment nodes are always skipped. META and STYLE elements are skipped only
   * in auto-match mode; in raw-HTML mode (autoMatchFormat: false) they are passed
   * through so downstream strategies can decide how to handle them.
   *
   * @param {HTMLElement} element - The element to check.
   * @param {VegaRTETransformOptions} options - Transform options.
   * @returns {boolean} True when the element should be skipped.
   */
  isInvalidElement(element, options) {
    if (element.nodeType === Node.COMMENT_NODE)
      return true;
    if (options.autoMatchFormat === false)
      return false;
    return ['META', 'STYLE'].includes(element.nodeName);
  }
  /**
   * Get the register element to block strategies.
   *
   * @returns {ElementToDTOStrategy[]} - The register element to block strategies.
   */
  getElementToBlockStrategies() {
    return ElementToDTOClassStrategyManager.getElementToBlockStrategies();
  }
}
export default new ElementToDtoStrategyProcessor();
