import remoteInvocationRegistry from '../../../../../helpers/remote-invocation/remote-invocation-registry';
import domNodeSubjectFactory from '../../../../../helpers/change-manager/subject/dom-node-subject/dom-node-subject-factory';
import { VegaInternalPopoverUpdateTarget } from '../../../../../helpers/event-manager/event-id/vega-internal-event-id';
import { TableSettingType, } from '../setting-event-handlers/setting-event-handler.abstract';
import { RowOperationEventHandler } from '../setting-event-handlers/row-operation';
import { CaptionOperationEventHandler } from '../setting-event-handlers/caption-operation';
import { ColumnOperationEventHandler } from '../setting-event-handlers/column-operation';
import { DomNodeSubjectObserverFactory } from '../../../../../helpers/change-manager/subject/dom-node-subject/dom-node-subject-observer-factory';
import { VegaPopoverShow } from '../../../../../helpers/event-manager/event-id/vega-event-id';
import { TableDynamicPopoverRenderer } from './table-dynamic-popover-renderer';
import { MergeCellsOperationEventHandler } from '../setting-event-handlers/merge-cells-operation';
import { SplitCellOperationEventHandler } from '../setting-event-handlers/split-cell-operation';
import { TablePopoverBaseRenderer } from './table-popover-base-renderer';
import { RTETableColorManager } from '../utils/table-color-manager';
import { tryGetDocument } from '../../../../../utils/try-get-document';
/**
 * Shared popover renderer for table settings.
 */
export class TableSettingPopoverRenderer extends TablePopoverBaseRenderer {
  constructor(renderContext) {
    super(renderContext);
    this.settingHandlers = [
      new RowOperationEventHandler(),
      new CaptionOperationEventHandler(),
      new ColumnOperationEventHandler(),
      new MergeCellsOperationEventHandler(),
      new SplitCellOperationEventHandler(),
    ];
    /**
     * Re-targets and shows the table setting popover for the clicked table.
     *
     * @param {MouseEvent} event - The MouseEvent that triggered the click.
     * @param {RTETableBlock} tableBlock - The clicked table's block data.
     * @param {() => HTMLElement} getTableRef - Getter for the clicked table's DOM element.
     */
    this.handleTableClick = (event, tableBlock, getTableRef) => {
      const target = event.target;
      const ownTrigger = target.closest('table');
      if (ownTrigger !== getTableRef()) {
        return;
      }
      // Prevent the click from bubbling to ancestor tables. When this is a nested
      // table click, the ancestor table still has the popover's stale click
      // listener attached (from when it was the popover's target), which would
      // toggle the popover off immediately after we show it.
      event.stopPropagation();
      this.reTarget(tableBlock, getTableRef);
      void this.tableDynamicPopover.hide();
      remoteInvocationRegistry.call(domNodeSubjectFactory.getSubject(this.popoverRef, VegaInternalPopoverUpdateTarget), ownTrigger);
      void this.popoverRef.show(true);
    };
    /**
     * Sync the selected cells from the table selection to the table setting component.
     */
    this.syncSelectedCells = () => {
      if (this.tableSettingRef) {
        this.tableSettingRef.selectedCells = this.getTableSelectedCells();
      }
    };
    /**
     * Handles setting menu click events.
     *
     * @param {CustomEvent<Array<string>>} event - The custom event emitted from the setting menu.
     */
    this.handleSettingMenuClick = (event) => {
      const handler = this.settingHandlers.find((handler) => handler.canHandle(event.detail));
      if (handler) {
        const extensionContext = this.getTableExtensionContext();
        extensionContext && handler.execute(event.detail, extensionContext, this.tableBlock);
        if (event.detail[0] === TableSettingType.CAPTION) {
          this.updateTableSettingCaption();
        }
      }
      if (event.detail[0] === TableSettingType.TABLE || event.detail[0] === TableSettingType.CELL) {
        void this.popoverRef.hide();
        void this.tableDynamicPopover.show(event.detail[0]);
      }
    };
    /**
     * Handles the popover show event to sync the selected table cells to the table setting component.
     */
    this.handleTableSettingPopoverShow = () => {
      this.syncSelectedCells();
    };
    this.tableDynamicPopover = new TableDynamicPopoverRenderer(RTETableColorManager.getTableColors(), renderContext);
  }
  /**
   * Destroys the dynamic popover renderer and removes the container from the DOM.
   */
  destroy() {
    this.tableDynamicPopover.destroy();
    if (this.popoverContainer) {
      this.popoverContainer.remove();
    }
  }
  /**
   * Builds the popover DOM and appends it to the RTE host. Idempotent: subsequent calls are no-ops.
   */
  render() {
    const safeDocument = tryGetDocument();
    if (safeDocument && this.renderContext) {
      this.popoverContainer = safeDocument.createElement('div');
      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
      this.renderContext.host.appendChild(this.popoverContainer);
      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
      const tableCellPopover = this.tableDynamicPopover.render();
      const popover = safeDocument.createElement('vega-popover');
      popover.trigger = 'click';
      popover.isScreenPosition = true;
      popover.className = 'rte-table-setting-popover';
      DomNodeSubjectObserverFactory.addUniqueObserverToNode(popover, VegaPopoverShow, this.handleTableSettingPopoverShow);
      const slotDiv = safeDocument.createElement('div');
      slotDiv.setAttribute('slot', 'popover');
      const tableSetting = safeDocument.createElement('vega-rich-text-table-setting');
      tableSetting.addEventListener('vegaClick', this.handleSettingMenuClick);
      slotDiv.appendChild(tableSetting);
      popover.appendChild(slotDiv);
      this.popoverContainer.appendChild(popover);
      this.popoverContainer.appendChild(tableCellPopover);
      this.popoverRef = popover;
      this.tableSettingRef = tableSetting;
    }
  }
  /**
   * Updates the table setting component caption state to match the current table data.
   */
  updateTableSettingCaption() {
    const hasCaption = this.tableBlock.hasCaption();
    if (this.tableSettingRef && this.tableSettingRef.hasCaption !== hasCaption) {
      this.tableSettingRef.hasCaption = hasCaption;
    }
  }
  /**
   * Re-targets the shared popovers to the given table.
   *
   * @param {RTETableBlock} tableBlock - The clicked table's block data.
   * @param {() => HTMLElement} getTableRef - Getter for the clicked table's DOM element.
   */
  reTarget(tableBlock, getTableRef) {
    if (this.tableSettingRef) {
      this.tableBlock = tableBlock;
      this.tableSettingRef.target = getTableRef();
      this.tableSettingRef.selectedCells = this.getTableSelectedCells();
      this.tableDynamicPopover.reTarget(tableBlock, getTableRef);
    }
  }
  /**
   * Collects and returns the currently selected table cells.
   *
   * @returns {RTETableCellBlock[]} The array of currently selected table cell blocks.
   */
  getTableSelectedCells() {
    let selectedCells = [];
    const extensionContext = this.getTableExtensionContext();
    if (extensionContext && extensionContext.tableSelection) {
      const { tableSelection } = extensionContext;
      selectedCells = tableSelection.getSelectedCells();
    }
    return selectedCells;
  }
}
