import { generateUUID } from '../../../../../utils/misc';
import { AppendChildrenAction } from '../../../dto/actions/append-child-nodes-action';
import { InsertChildrenBeforeAction } from '../../../dto/actions/insert-children-before-block';
import { RTETableBodyBlock } from '../dto/table-body-block';
import { RTETableRowBlock } from '../dto/table-row-block';
import { TableRowCommonUtilitiesStrategy } from './table-row-strategy.abstract';
/**
 * Strategy class for handling the insertion of a new row into a table.
 * The reference row is head row and the insert direction is below, so the new row will be inserted into the body section.
 */
export class InsertTableRowIntoDifferentSectionStrategy extends TableRowCommonUtilitiesStrategy {
  /**
   * @inheritDoc
   */
  handleAction(action, target) {
    const { selectedRows } = action;
    const refBlock = selectedRows[selectedRows.length - 1];
    let tableBody = target.children.find((block) => block instanceof RTETableBodyBlock);
    const rowBlockJSON = {
      id: generateUUID(),
      type: 'table-row',
      children: [],
    };
    let headCellLength = 0;
    let firstBodyRow = null;
    if (!tableBody) {
      tableBody = RTETableBodyBlock.from({
        id: generateUUID(),
        type: 'table-body',
        children: [],
      });
      target.apply(new AppendChildrenAction([tableBody]));
    }
    else {
      firstBodyRow = tableBody.children[0];
      headCellLength = this.getHeadCellLength(firstBodyRow);
    }
    const allHeaderRows = refBlock.parent.children;
    const rowCellMaxCount = this.getRowsMaxCellCount(allHeaderRows);
    const refRowCellCount = this.getRowsMaxCellCount([refBlock]);
    // If the reference row has less cells than the max cell count in the section, we need to add new cell to make it up to the max count.
    if (refRowCellCount < rowCellMaxCount) {
      const rowIndex = allHeaderRows.indexOf(refBlock);
      const rowStartCols = this.getRowCellStartCols(allHeaderRows);
      const rowCellMap = new Map();
      for (let i = 0; i < rowCellMaxCount; i++) {
        const cellType = i < headCellLength ? 'table-head-cell' : 'table-cell';
        const { cell } = this.getTheStartSpanCell(allHeaderRows, rowStartCols, rowIndex, i);
        if (cell) {
          const colSpan = cell.colSpan;
          rowCellMap.set(i, this.getDefaultCellBlockTemplate(cellType, colSpan));
          i += colSpan - 1;
        }
      }
      rowBlockJSON.children = this.getSortedValuesByNumericKey(rowCellMap);
    }
    else {
      rowBlockJSON.children = this.createTableCells(refBlock, headCellLength);
    }
    const insertAction = firstBodyRow
      ? new InsertChildrenBeforeAction(firstBodyRow, RTETableRowBlock.from(rowBlockJSON))
      : new AppendChildrenAction([RTETableRowBlock.from(rowBlockJSON)]);
    tableBody.apply(insertAction);
  }
  /**
   * Create table cells based on reference row and head cell length.
   *
   * @param {RTETableRowBlock} refRow - The reference table row block.
   * @param {number} headCellLength - The length of the head cells.
   * @returns {VegaRTETableCellBlock[]} An array of table cell blocks.
   */
  createTableCells(refRow, headCellLength) {
    const cells = [];
    let currentHeadCellLength = 0;
    for (const cell of refRow.children) {
      const isHeadCell = currentHeadCellLength < headCellLength;
      const cellType = isHeadCell ? 'table-head-cell' : 'table-cell';
      cells.push(this.getDefaultCellBlockTemplate(cellType, cell.colSpan));
      currentHeadCellLength += cell.colSpan;
    }
    return cells;
  }
}
