import { Renderable } from '../core/renderable.js';
import { nodeFactory } from './node-factory.js';
import { normalize } from '@gouvfr/dsfr-kit';
import { TagAttributes } from '@gouvfr/dsfr-forge';
class Node extends Renderable {
  constructor (data, tagName = null, isSelfClosing = false, hasNormalizedId = false) {
    super(data);
    this._tagName = tagName || this.data.tagName;
    this._isSelfClosing = isSelfClosing;
    this._hasNormalizedId = hasNormalizedId;
    this._type = this.data.type;
    this._children = Array.isArray(this.data.children) ? this.data.children.map(childData => nodeFactory.create(childData)) : [];
    if (typeof this.data?.attributes === 'object' && Object.keys(this.data.attributes).length > 0) {
      Object.entries(this.data.attributes).forEach(([key, value]) => {
        switch (key) {
          case 'classes':
            if (typeof value === 'string') {
              this.attributes.setClasses(value.split(' '));
            } else if (Array.isArray(value)) {
              this.attributes.setClasses(value);
            }
            break;

          default:
            this.attributes.setAttribute(key, value);
        }

      });
    }
    if (typeof this.data?.classes === 'object' && Array.isArray(this.data.classes)) {
      this.attributes.setClasses(this.data.classes);
    }

    if (this.hasNormalizedId) {
      this._normalizedId = normalize(this.text);
      this.attributes.setAttribute('id', this._normalizedId);
    }
  }

  get children () {
    return this._children;
  }

  get type () {
    return this._type;
  }

  set tagName (value) {
    this._tagName = value;
  }

  get tagName () {
    return this._tagName;
  }

  get isSelfClosing () {
    return this._isSelfClosing;
  }

  get hasNormalizedId () {
    return this._hasNormalizedId;
  }

  get normalizedId () {
    return this._normalizedId;
  }

  get attributes () {
    if (!this._attributes) {
      this._attributes = new TagAttributes();
    }
    return this._attributes;
  }

  renderAttributes () {
    return this._attributes ? this._attributes.render() : '';
  }

  getAttributes () {
    return this._attributes ? this._attributes.getAttributes() : {};
  }

  findDescendantsByType (type) {
    const descendants = [];
    for (const child of this._children) {
      if (child.type === type) descendants.push(child);
      descendants.push(...child.findDescendantsByType(type));
    }
    return descendants;
  }

  async renderChildren () {
    let html = '';
    for (const child of this._children) {
      html += await child.render();
    }
    return html;
  }

  async render () {
    const innerHtml = await this.renderChildren();

    if (!this.tagName) return innerHtml;

    return this.isSelfClosing ? `<${this.tagName}${this.renderAttributes()}/>` : `<${this.tagName}${this.renderAttributes()}>${innerHtml}</${this.tagName}>`;
  }

  get text () {
    return this._children.map(child => child.text).join(' ');
  }

  static getImageChild (data) {
    if (data.type === 'image') return data;
    if (data.children) {
      for (const child of data.children) {
        const image = Node.getImageChild(child);
        if (image) return image;
      }
    }
    return null;
  }
}

export { Node };
