var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { InjectVegaSlimmer, MapToComponentField, MapToComponentMethod, methodPlaceholder, VegaSlimmer, } from 'vega-slimmer/core';
import { isNonNullable } from '../../../../types/type-guard';
import { PageResizeObserverSlimmer } from '../../../../helpers/slimmers/page-resize-observer-slimmer';
import { extractNumberFromString } from '../../../../utils/ui';
import { SynchronizeTaskQueue } from '../../../../helpers/queue/synchronize-task-queue';
export class VegaTablePinnedRenderer extends VegaSlimmer {
  constructor() {
    super(...arguments);
    this.pageResizeObserverSlimmer = new PageResizeObserverSlimmer({
      // eslint-disable-next-line
      target: () => this.host.shadowRoot.querySelector('table'),
      isDeferred: true,
      /*
       * The below method is e2e-test covered in
       * @see{module:resize-pinned-position-by-edit-row}
       */
      callback: /* istanbul ignore next */ async () => {
        await this.host.componentOnReady().then(() => {
          this.updateTableRowPinnedPosition();
          this.updateTableCellPinnedPosition();
        });
      },
    });
    this.previouslyStyledCells = new Set();
    this.clearPinnedPositionsTaskQueue = new SynchronizeTaskQueue(1);
  }
  componentDidLoad() {
    methodPlaceholder;
  }
  async componentDidRender() {
    await this.clearPinnedPositionsTaskQueue.runTask();
    this.updateTableRowPinnedPosition();
    this.updateTableCellPinnedPosition();
  }
  watchColumnStructureModel() {
    void this.clearPinnedPositionsTaskQueue.enqueue({
      run: async () => {
        this.clearAllPinnedPositions();
      },
    }, false);
  }
  updateTableCellPinnedPosition() {
    if (!this.columnStructureModel.hasLeftPinnedColumn() &&
      !this.columnStructureModel.hasRightPinnedColumn())
      return;
    // if not have head row, it means no pinned, so no need to update
    const row = this.host.shadowRoot.querySelector('vega-table-head-row');
    // to avoid window resize before table rendered.
    // @see{module:resize-pinned-position-by-edit-row}
    /* istanbul ignore next */
    if (!row)
      return;
    const headCellRenderInputMap = this.vegaTableRenderInputController.getHeadCellRenderInputMap();
    const pinnedColumnBodyCellRenderInputMap = this.vegaTableRenderInputController.getPinnedColumnBodyCellRenderInputMap();
    const [prevShadowThWidth, nextShadowThWidth] = this.getRowShadowThWidths();
    const leafWidths = this.getLeafWidths();
    headCellRenderInputMap.forEach((renderInput, headCell) => {
      this.updateCellPinnedPosition(renderInput, headCell, prevShadowThWidth, leafWidths, nextShadowThWidth);
    });
    pinnedColumnBodyCellRenderInputMap.forEach((renderInput, headCell) => {
      this.updateCellPinnedPosition(renderInput, headCell, prevShadowThWidth, leafWidths, nextShadowThWidth);
    });
  }
  getRowShadowThWidths() {
    const row = this.host.shadowRoot.querySelector('vega-table-head-row');
    const rowShadow = row.shadowRoot;
    const firstTh = rowShadow.querySelector('th:first-of-type');
    const draggableTh = rowShadow.querySelector('.vega-table-draggable-column');
    const selectionTh = rowShadow.querySelector('.vega-table-selection-column');
    const expandTh = rowShadow.querySelector('.vega-table-expand-action-column');
    const lastTh = rowShadow.querySelector('th:last-of-type');
    if (firstTh) {
      const prevWidth = firstTh.getBoundingClientRect().width +
        ((selectionTh === null || selectionTh === void 0 ? void 0 : selectionTh.getBoundingClientRect().width) || 0) +
        ((draggableTh === null || draggableTh === void 0 ? void 0 : draggableTh.getBoundingClientRect().width) || 0);
      const nextWidth = ((expandTh === null || expandTh === void 0 ? void 0 : expandTh.getBoundingClientRect().width) || 0) + lastTh.getBoundingClientRect().width;
      return [prevWidth, nextWidth];
    }
    // to avoid window resize before row rendered.
    // @see{module:resize-pinned-position-by-edit-row}
    /* istanbul ignore next */
    return [0, 0];
  }
  getLeafWidths() {
    const headCellRenderInputMap = this.vegaTableRenderInputController.getHeadCellRenderInputMap();
    const leafRenderInputs = this.vegaTableRenderInputController.getLeafRenderInputs();
    return leafRenderInputs.map((leaf) => {
      var _a;
      for (const [cell, renderInput] of headCellRenderInputMap.entries()) {
        if (leaf === renderInput) {
          // to avoid window resize before cell rendered.
          // @see{module:resize-pinned-position-by-edit-row}
          /* istanbul ignore next */
          return ((_a = cell.shadowRoot.querySelector('th, td')) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().width) || 0;
        }
      }
    });
  }
  updateCellPinnedPosition(renderInput, headCell, prevShadowThWidth, leafWidths, nextShadowThWidth) {
    if (['left', 'right'].includes(renderInput.pinned)) {
      const shadowCell = headCell.shadowRoot.querySelector('th, td');
      if (renderInput.pinned === 'left') {
        const position = prevShadowThWidth +
          leafWidths
            .slice(0, renderInput.columnIndex)
            .reduce((count, colWidth) => count + colWidth, 0);
        this.updatePinnedPosition(shadowCell, 'left', position);
      }
      if (renderInput.pinned === 'right') {
        const colSpan = isNonNullable(renderInput.colSpan) ? renderInput.colSpan : 1;
        const position = nextShadowThWidth +
          leafWidths
            .slice(renderInput.columnIndex + (colSpan - 1) + 1)
            .reduce((count, colWidth) => count + colWidth, 0);
        this.updatePinnedPosition(shadowCell, 'right', position);
      }
    }
  }
  updateTableRowPinnedPosition() {
    const hasLeftPinnedColumn = this.columnStructureModel.hasLeftPinnedColumn();
    const hasRightPinnedColumn = this.columnStructureModel.hasRightPinnedColumn();
    const tableWidth = this.host.getBoundingClientRect().width;
    const leftPadding = extractNumberFromString(this.paddingX[0]);
    const rightPadding = extractNumberFromString(this.paddingX[1]);
    // table width - padding(8*2) - border(2);
    const expandContainerWidth = tableWidth - leftPadding - rightPadding - 2;
    this.host.shadowRoot
      .querySelectorAll('vega-table-head-row, vega-table-row, vega-table-expand-row')
      .forEach((row) => {
      const rowShadow = row.shadowRoot;
      if (hasLeftPinnedColumn) {
        const firstCell = rowShadow.querySelector('th:first-of-type, td:first-of-type');
        const selectionCell = rowShadow.querySelector('.vega-table-selection-column');
        const draggableCell = rowShadow.querySelector('.vega-table-draggable-column');
        this.updatePinnedPosition(firstCell, 'left', 0);
        this.updatePinnedPosition(draggableCell, 'left', leftPadding);
        const draggableCellWidth = (draggableCell === null || draggableCell === void 0 ? void 0 : draggableCell.getBoundingClientRect().width) || 0;
        this.updatePinnedPosition(selectionCell, 'left', leftPadding + draggableCellWidth);
      }
      if (hasRightPinnedColumn) {
        const expandCell = rowShadow.querySelector('.vega-table-expand-action-column');
        const lastCell = rowShadow.querySelector('th:last-of-type, td:last-of-type');
        this.updatePinnedPosition(expandCell, 'right', rightPadding);
        this.updatePinnedPosition(lastCell, 'right', 0);
      }
      if (hasRightPinnedColumn || hasLeftPinnedColumn) {
        const expandCell = rowShadow.querySelector('.vega-table-expanded-row-slot-container');
        if (expandCell) {
          const slotInnerContainer = expandCell.querySelector('.expanded-row-slot-inner');
          this.updatePinnedPosition(slotInnerContainer, 'left', leftPadding);
          // we should set the width to make the expand slot not scroll by table scroll.
          // ticket: https://gethired.atlassian.net/browse/VD-7015
          slotInnerContainer.style.width = `${expandContainerWidth}px`;
        }
      }
    });
  }
  clearAllPinnedPositions() {
    this.previouslyStyledCells.forEach((cell) => {
      cell.style.position = '';
      cell.style.zIndex = '';
      cell.style.left = '';
      cell.style.right = '';
      if (cell.classList.contains('expanded-row-slot-inner')) {
        cell.style.width = '';
      }
    });
    this.previouslyStyledCells.clear();
  }
  updatePinnedPosition(cell, type, position) {
    if (!cell)
      return;
    cell.style.position = 'sticky';
    cell.style.zIndex = '1';
    cell.style[type] = `${position}px`;
    this.previouslyStyledCells.add(cell);
  }
}
__decorate([
  MapToComponentField()
], VegaTablePinnedRenderer.prototype, "host", void 0);
__decorate([
  MapToComponentField()
], VegaTablePinnedRenderer.prototype, "columnStructureModel", void 0);
__decorate([
  MapToComponentField()
], VegaTablePinnedRenderer.prototype, "paddingX", void 0);
__decorate([
  MapToComponentField()
], VegaTablePinnedRenderer.prototype, "vegaTableRenderInputController", void 0);
__decorate([
  InjectVegaSlimmer()
], VegaTablePinnedRenderer.prototype, "pageResizeObserverSlimmer", void 0);
__decorate([
  MapToComponentMethod('componentDidLoad')
], VegaTablePinnedRenderer.prototype, "componentDidLoad", null);
__decorate([
  MapToComponentMethod('componentDidRender')
], VegaTablePinnedRenderer.prototype, "componentDidRender", null);
__decorate([
  MapToComponentMethod('watchColumnStructureModel')
], VegaTablePinnedRenderer.prototype, "watchColumnStructureModel", null);
