import React, { useMemo } from 'react';
import { CHECKBOXES_COLUMN, COLUMN_SIZE, ROW_ACTIONS_COLUMN, EXPAND_TOGGLE_COLUMN } from '../types';
import { CheckboxHeaderCell, CheckboxBodyCell, RowExpandCell, TableRowActionsCell } from '../components/custom-cells';
import { useTranslation } from '../../hooks/use-translation';
import { SKELETON_TYPES } from '../../skeleton';
import { jsx as _jsx } from "react/jsx-runtime";
function calculateDelta(columns, maxWidth, padding = 0, columnSizing = {}, visibility = {}) {
  // we are interested only in visible columns
  const visibleColumns = columns.filter(({
    accessorKey,
    id
  }) => {
    // visibility state uses column ids for setting visibility, and for most cases it's the same as accessorKey
    // but for the case when either 1) user provided an explicit id to the columnDef or 2) accessorKey is a complex get object path like `<object_name>.<object_property_name>`
    // accessorKey would be different from id. Thus we should add a check on columnDef.id here
    const visibilityValue = visibility[id] ?? visibility[accessorKey];
    return visibilityValue !== false;
  });
  // we need to know columns that do have maxSize set, as it will influence how free space is distributed
  const columnsWithMaxSize = visibleColumns.filter(column => !!column.maxSize);

  // calculation of all current columns width
  const currentWidth = visibleColumns.reduce((acc, current) => {
    const resizeValue = columnSizing[current.id] || columnSizing[current.accessorKey];
    const minWidth = current.minSize || COLUMN_SIZE.MIN_WIDTH;
    const resizeWidth = resizeValue ? Math.max(resizeValue, minWidth) : 0;
    const columnSize = Math.max(current.size || COLUMN_SIZE.WIDTH, minWidth);
    return acc + (resizeWidth || columnSize);
  }, padding);

  // if sum of al columns is greater than container width, no free space to distribute
  if (currentWidth > maxWidth) {
    return {};
  }

  // all free space available for distribution
  const delta = maxWidth - currentWidth;
  // selecting columns among which to distribute free space. (Filtering out columns that have eiterh size set in their columnDef, or ones
  // whose size was altered manually by drag-n-drop in UI)
  const notSettedColumns = visibleColumns.filter(({
    size,
    accessorKey,
    id
  }) => !size && !(columnSizing[id] || columnSizing[accessorKey]));
  const evenDistribution = delta / notSettedColumns.length;

  // if there is no max size on any columns - distribute free space evenly across columns
  if (columnsWithMaxSize.length === 0) {
    return notSettedColumns.reduce((acc, column) => {
      acc[column.accessorKey] = evenDistribution;
      return acc;
    }, {});
  }

  // get columns withMaxSize where column.currentSize + delta > column.maxSize
  // and give them the portion of delta to reach maxSize
  const columnsWithCappedDelta = columnsWithMaxSize.reduce((acc, current) => {
    const minWidth = current.minSize || COLUMN_SIZE.MIN_WIDTH;
    const columnSize = Math.max(current.size || COLUMN_SIZE.WIDTH, minWidth);
    if (columnSize + evenDistribution > current.maxSize) {
      acc[current.accessorKey] = current.maxSize - columnSize;
    }
    return acc;
  }, {});

  // calculate delta left after columns which reached max size are given their deltas
  const evenlyDistributedSpaceAfterMaxSized = (delta - Object.values(columnsWithCappedDelta).reduce((acc, item) => acc + item, 0)) / (notSettedColumns.length - Object.values(columnsWithCappedDelta).length);

  // return a map of <accessorKey>: <respectiveDelta> for all visible columns
  return notSettedColumns.reduce((acc, notSettedColumn) => {
    // if current column has maxSize corner case - take delta from previously computed columnsWithCappedDelta
    if (columnsWithCappedDelta[notSettedColumn.accessorKey]) {
      acc[notSettedColumn.accessorKey] = columnsWithCappedDelta[notSettedColumn.accessorKey];
    } else {
      // otherwise use newly computed evenly distributed delta
      acc[notSettedColumn.accessorKey] = evenlyDistributedSpaceAfterMaxSized;
    }
    return acc;
  }, {});
}
export function useColumns(columns, showCheckboxes, maxWidth, visibility, columnSizing, showExpandRow, isRowActionsExist, localizationProps) {
  const {
    t
  } = useTranslation();
  const decoratedColumns = useMemo(() => {
    const checkBoxColumn = {
      id: CHECKBOXES_COLUMN.ID,
      accessorKey: CHECKBOXES_COLUMN.ID,
      header: ({
        table,
        keyboardNavCellId
      }) => /*#__PURE__*/_jsx(CheckboxHeaderCell, {
        table: table,
        keyboardNavCellId: keyboardNavCellId,
        selectAllRowsAriaLabel: localizationProps?.selectAllRowsCheckBoxAriaLabel
      }),
      cell: ({
        row,
        table,
        rowSelectionDisabled,
        keyboardNavCellId
      }) => /*#__PURE__*/_jsx(CheckboxBodyCell, {
        row: row,
        table: table,
        rowSelectionDisabled: rowSelectionDisabled,
        keyboardNavCellId: keyboardNavCellId,
        selectRowAriaLabel: localizationProps?.selectRowCheckBoxAriaLabel
      }),
      size: CHECKBOXES_COLUMN.SIZE,
      enableSorting: false,
      meta: {
        className: 'select-checkbox',
        hideFromSettings: true,
        hideSeparator: true,
        hideMenu: true,
        truncateText: false,
        hasCustomCellAction: true,
        loader: {
          type: SKELETON_TYPES.CIRCULAR,
          width: 16,
          height: 16
        },
        headerAriaLabel: localizationProps?.checkboxHeaderCellAriaLabel || t('Click to select all rows in the table'),
        cellAriaLabel: localizationProps?.checkBoxBodyCellAriaLabel || t('Click to select the row')
      }
    };
    const rowActionsColumn = {
      id: ROW_ACTIONS_COLUMN.ID,
      accessorKey: ROW_ACTIONS_COLUMN.ID,
      header: () => null,
      cell: ({
        row,
        getRowActions,
        getRowFooterAction,
        keyboardNavCellId
      }) => /*#__PURE__*/_jsx(TableRowActionsCell, {
        getRowActions: getRowActions || (() => []),
        getRowFooterAction: getRowFooterAction,
        row: row,
        rowActionsTriggerAriaLabel: localizationProps?.rowActionsTriggerAriaLabel,
        keyboardNavCellId: keyboardNavCellId
      }),
      size: ROW_ACTIONS_COLUMN.SIZE,
      enableSorting: false,
      meta: {
        className: 'row-actions',
        hideFromSettings: true,
        ariaHidden: true,
        hideSeparator: true,
        hideMenu: true,
        truncateText: false,
        hasCustomCellAction: true,
        loader: {
          type: SKELETON_TYPES.CIRCULAR,
          width: 16,
          height: 16
        },
        cellAriaLabel: localizationProps?.tableRowActionsAriaLabel || t('Click to open row actions dropdown')
      }
    };
    const rowExpandToggleColumn = {
      id: EXPAND_TOGGLE_COLUMN.ID,
      accessorKey: EXPAND_TOGGLE_COLUMN.ID,
      header: () => null,
      cell: props => /*#__PURE__*/_jsx(RowExpandCell, {
        ...props,
        expandRowButtonAriaLabel: localizationProps?.expandRowButtonAriaLabel
      }),
      size: EXPAND_TOGGLE_COLUMN.SIZE,
      enableSorting: false,
      meta: {
        className: 'row-expand-toggle',
        ariaHidden: true,
        hideFromSettings: true,
        hideSeparator: true,
        hideMenu: true,
        truncateText: false,
        hasCustomCellAction: true,
        loader: {
          type: SKELETON_TYPES.CIRCULAR,
          width: 16,
          height: 16
        },
        cellAriaLabel: localizationProps?.expandRowCellAriaLabel || t('Click to expand the row')
      }
    };
    const actionsCellWidth = isRowActionsExist ? ROW_ACTIONS_COLUMN.SIZE : 0;
    const checkBoxWidth = showCheckboxes ? CHECKBOXES_COLUMN.SIZE : 0;
    const expandRowCellWidth = showExpandRow ? EXPAND_TOGGLE_COLUMN.SIZE : 0;
    const columnsDelta = calculateDelta(columns, maxWidth, checkBoxWidth + actionsCellWidth + expandRowCellWidth, columnSizing, visibility);
    const updatedColumns = columns.map(col => ({
      minSize: col.minSize || COLUMN_SIZE.MIN_WIDTH,
      maxSize: col.maxSize || COLUMN_SIZE.MAX_WIDTH,
      size: columnSizing[col.accessorKey] || Math.max(COLUMN_SIZE.WIDTH, col.minSize ?? 0) + (columnsDelta[col.accessorKey] ?? 0),
      ...col,
      meta: {
        truncateText: !col.cell,
        ...(col.meta || {})
      }
    }));
    return [...(showExpandRow ? [rowExpandToggleColumn] : []), ...(showCheckboxes ? [checkBoxColumn] : []), ...updatedColumns, ...(isRowActionsExist ? [rowActionsColumn] : [])];
  }, [maxWidth, visibility, showCheckboxes, isRowActionsExist, columns, showExpandRow]);
  return decoratedColumns;
}