import { RTEBlock } from '../../../dto/blocks/block.abstract';
import { RTETableExtensionAnnotationTypeEnum, RTETableAnnotation, } from '../annotations/table-annotation';
import { isNonNullable } from '../../../../../types/type-guard';
/**
 * Class representing a table block in the rich text editor.
 */
export class RTETableBlock extends RTEBlock {
  constructor(id, options) {
    super(id);
    this.type = 'table-block';
    this.children = [];
    const { autoMatchFormat } = options || { autoMatchFormat: true };
    if (autoMatchFormat) {
      this.annotationMap.set(RTETableExtensionAnnotationTypeEnum.TABLE, new RTETableAnnotation());
    }
  }
  /**
   * @inheritDoc
   */
  static from(block, options) {
    var _a;
    const tableBlock = new RTETableBlock(block.id, options);
    super.convertAnnotationsToMap(tableBlock.annotationMap, Object.assign({}, block.annotations));
    tableBlock.children = super.generateBlockChildren(block.children, options, tableBlock);
    if ((_a = block.annotations) === null || _a === void 0 ? void 0 : _a.table) {
      tableBlock.annotationMap.set(...RTETableAnnotation.from(block.annotations.table, options === null || options === void 0 ? void 0 : options.autoMatchFormat));
    }
    return tableBlock;
  }
  /**
   * @inheritDoc
   */
  clone(parent) {
    const clonedBlock = new RTETableBlock(this.id);
    clonedBlock.children = this.children.map((child) => child.clone(clonedBlock));
    clonedBlock.parent = parent;
    clonedBlock.annotationMap = super.cloneAnnotations();
    return clonedBlock;
  }
  /**
   * @inheritDoc
   */
  getLastNode() {
    return this.children[this.children.length - 1].getLastNode();
  }
  /**
   * Get the first node of the table block.
   *
   * @returns {RTENode} The first node of the table block.
   */
  getFirstNode() {
    if (this.hasCaption()) {
      return this.children[0].children[0].getLastNode();
    }
    else {
      const childNode = this.children[0].children[0]
        .children[0];
      return childNode.getLastNode();
    }
  }
  /**
   * @inheritDoc
   */
  isNotEmpty() {
    return this.children.length > 0;
  }
  /**
   * @inheritDoc
   */
  toHtml(options) {
    const childrenHtml = this.children.map((child) => child.toHtml(options)).join('');
    const attrStr = super.generateAttributeString(options);
    return `<table${attrStr}>${childrenHtml}</table>`;
  }
  /**
   * @inheritDoc
   */
  toJSON() {
    return Object.assign(Object.assign({}, super.toJSON()), { type: this.type, children: this.children.map((child) => child.toJSON()) });
  }
  /**
   * Retrieves the caption block from the children collection, if present.
   *
   * @returns {Nullable<RTETableCaptionBlock>} The caption block or `null`.
   */
  getCaption() {
    const caption = this.children.find((child) => child.type === 'table-caption');
    return caption !== null && caption !== void 0 ? caption : null;
  }
  /**
   * Inserts, replaces, or removes the caption block within the children.
   *
   * @param {Nullable<RTETableCaptionBlock>} caption - The caption block to set, or `null` to remove.
   */
  setCaption(caption) {
    const index = this.children.findIndex((child) => child.type === 'table-caption');
    if (!caption) {
      if (index >= 0) {
        this.children.splice(index, 1);
      }
      return;
    }
    caption.parent = this;
    if (index >= 0) {
      this.children[index] = caption;
    }
    else {
      this.children.unshift(caption);
    }
  }
  /**
   * Checks whether the table currently stores a caption block reference.
   *
   * @returns {boolean} `true` when a caption DTO is attached; otherwise `false`.
   */
  hasCaption() {
    return isNonNullable(this.getCaption());
  }
}
