import _Checkbox from "@mui/material/Checkbox";
/*!
 * Copyright (c) 2023-present, Okta, Inc. and/or its affiliates. All rights reserved.
 * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
 *
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *
 * See the License for the specific language governing permissions and limitations under the License.
 */
import { MRT_TableContainer, useMaterialReactTable } from "material-react-table";
import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
import { Box } from "../Box.js";
import { MenuButton } from "../Buttons/MenuButton.js";
import { MenuItem } from "../Buttons/MenuItem.js";
import { useTranslation } from "../i18n.generated/i18n.js";
import { ArrowBottomIcon, ArrowDownIcon, ArrowTopIcon, ArrowUnsortedIcon, ArrowUpIcon, DragIndicatorIcon, ListIcon, MoreIcon, ShowIcon } from "../icons.generated/index.js";
import { useOdysseyDesignTokens } from "../OdysseyDesignTokensContext.js";
import { DataFilters } from "./DataFilters.js";
import { DataTablePagination } from "./DataTablePagination.js";
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
export const densityValues = ["comfortable", "spacious", "compact"];
const reorderDataRowsLocally = ({
  currentData,
  rowId,
  newIndex
}) => {
  const updatedData = [...currentData];
  const rowIndex = updatedData.findIndex(row => row.id === rowId);
  if (rowIndex !== -1) {
    const [removedRow] = updatedData.splice(rowIndex, 1);
    updatedData.splice(newIndex, 0, removedRow);
  }
  return updatedData;
};
const DataTable = ({
  columns,
  data: dataProp,
  getRowId,
  page: pageProp = 1,
  initialDensity = densityValues[0],
  resultsPerPage: resultsPerPageProp = 20,
  fetchDataFn,
  reorderDataFn,
  totalRows,
  hasSearchSubmitButton,
  searchDelayTime,
  paginationType = "paged",
  onRowSelectionChange,
  rowActionButtons,
  rowActionMenuItems,
  hasChangeableDensity,
  hasColumnResizing,
  hasColumnVisibility,
  hasFilters,
  hasPagination,
  hasRowReordering,
  hasRowSelection,
  hasSearch,
  hasSorting
}) => {
  const odysseyDesignTokens = useOdysseyDesignTokens();
  const {
    t
  } = useTranslation();
  const [draggingRow, setDraggingRow] = useState();
  const [showSkeletons, setShowSkeletons] = useState(true);
  const [data, setData] = useState(dataProp);
  const [page, setPage] = useState(pageProp);
  const [resultsPerPage, setResultsPerPage] = useState(resultsPerPageProp);
  const [rowSelection, setRowSelection] = useState({});
  const [sorting, setSorting] = useState([]);
  const [density, setDensity] = useState(initialDensity);
  const initialColumnVisibility = useMemo(() => {
    return columns.reduce((acc, column) => {
      acc[column.accessorKey] = true;
      return acc;
    }, {});
  }, [columns]);
  const [columnVisibility, setColumnVisibility] = useState(initialColumnVisibility);
  const [globalFilter, setGlobalFilter] = useState("");
  const [filters, setFilters] = useState();
  useEffect(() => {
    setShowSkeletons(false);
  }, [data]);
  useEffect(() => {
    onRowSelectionChange?.(rowSelection);
  }, [rowSelection, onRowSelectionChange]);
  const refreshData = useCallback(async () => {
    setShowSkeletons(true);
    try {
      const newData = fetchDataFn({
        page: page,
        resultsPerPage: resultsPerPage,
        sort: sorting,
        search: globalFilter,
        filters: filters
      });
      setData(newData instanceof Promise ? await newData : newData);
      setShowSkeletons(false);
    } catch (error) {
      console.error(error);
      setShowSkeletons(false);
    }
  }, [page, resultsPerPage, sorting, globalFilter, filters, fetchDataFn]);
  useEffect(() => {
    refreshData();
  }, [refreshData, page, resultsPerPage, sorting, globalFilter, filters]);
  const handleSortingChange = useCallback(updater => {
    setSorting(prevSorting => updater instanceof Function ? updater(prevSorting) : sorting);
  }, [sorting]);
  const handleColumnVisibility = useCallback(columnId => {
    setColumnVisibility(prevVisibility => ({
      ...prevVisibility,
      [columnId]: !columnVisibility[columnId]
    }));
  }, [columnVisibility]);
  const handleSearch = useCallback(value => {
    setGlobalFilter(value);
  }, []);
  const handleFilters = useCallback(updatedFilters => {
    setFilters(updatedFilters);
  }, []);
  const handleRowSelectionChange = useCallback(updater => {
    setRowSelection(prevRowSelection => updater instanceof Function ? updater(prevRowSelection) : rowSelection);
  }, [rowSelection]);
  const updateRowOrder = useCallback(({
    rowId,
    newIndex
  }) => {
    if (newIndex < 0) {
      return;
    }
    if (totalRows && newIndex > totalRows) {
      return;
    }
    const newData = reorderDataRowsLocally({
      currentData: data,
      rowId,
      newIndex
    });
    setData(newData);
    reorderDataFn?.({
      rowId,
      newIndex
    });
    refreshData();
  }, [data, totalRows, reorderDataFn, refreshData]);
  const rowVirtualizerInstanceRef = useRef(null);
  const setHoveredRow = useCallback((table, id) => {
    if (id) {
      const nextRow = table.getRow(id);
      if (nextRow) {
        table.setHoveredRow(nextRow);
      }
    }
  }, []);
  const resetDraggingAndHoveredRow = useCallback(table => {
    setDraggingRow(null);
    table.setHoveredRow(null);
  }, [setDraggingRow]);
  const handleDragHandleKeyDown = useCallback(({
    table,
    row,
    event
  }) => {
    const {
      hoveredRow
    } = table.getState();
    const {
      key
    } = event;
    const isSpaceKey = key === " ";
    const isEnterKey = key === "Enter";
    const isEscapeKey = key === "Escape";
    const isArrowDown = key === "ArrowDown";
    const isArrowUp = key === "ArrowUp";
    const isSpaceOrEnter = isSpaceKey || isEnterKey;
    const zeroIndexedPageNumber = page - 1;
    const currentIndex = row.index + zeroIndexedPageNumber * resultsPerPage;
    if (isEscapeKey) {
      resetDraggingAndHoveredRow(table);
      return;
    }
    if (isSpaceOrEnter) {
      event.preventDefault();
      event.stopPropagation();
    }
    if (draggingRow) {
      if (typeof hoveredRow?.index === "number") {
        const {
          index
        } = hoveredRow;
        if (isSpaceOrEnter) {
          const pageRelativeIndex = index + zeroIndexedPageNumber * resultsPerPage;
          if (pageRelativeIndex !== currentIndex) {
            updateRowOrder({
              rowId: row.id,
              newIndex: pageRelativeIndex
            });
            setTimeout(() => {
              resetDraggingAndHoveredRow(table);
            }, odysseyDesignTokens.TransitionDurationMainAsNumber);
            return;
          }
        }
        if (isArrowDown || isArrowUp) {
          const nextIndex = isArrowDown ? index + 1 : index - 1;
          setHoveredRow(table, data[nextIndex]?.id);
        }
      } else {
        if (isArrowDown || isArrowUp) {
          const nextIndex = isArrowDown ? row.index + 1 : row.index - 1;
          setHoveredRow(table, data[nextIndex]?.id);
        }
      }
    } else {
      if (isSpaceOrEnter) {
        setDraggingRow(row);
      }
    }
  }, [data, draggingRow, odysseyDesignTokens.TransitionDurationMainAsNumber, page, resetDraggingAndHoveredRow, resultsPerPage, setHoveredRow, updateRowOrder]);
  const handleDragHandleOnDragEnd = useCallback(table => {
    const cols = table.getAllColumns();
    cols[0].toggleVisibility();
    const {
      draggingRow,
      hoveredRow
    } = table.getState();
    if (draggingRow) {
      updateRowOrder({
        newIndex: hoveredRow.index,
        rowId: draggingRow.id
      });
    }
    setDraggingRow(null);
  }, [updateRowOrder]);
  const handleDragHandleOnDragCapture = useCallback(table => {
    if (!draggingRow && table.getState().draggingRow?.id) {
      setDraggingRow(table.getState().draggingRow);
    }
  }, [draggingRow]);
  const tableState = useMemo(() => ({
    density,
    sorting,
    globalFilter,
    columnVisibility,
    rowSelection,
    showSkeletons
  }), [density, sorting, globalFilter, columnVisibility, rowSelection, showSkeletons]);
  const table = useMaterialReactTable({
    columns: columns,
    data: data,
    state: tableState,
    rowVirtualizerInstanceRef: rowVirtualizerInstanceRef,
    rowVirtualizerOptions: {
      overscan: 4
    },
    enableRowVirtualization: paginationType === "loadMore" || resultsPerPage > 50,
    enableColumnResizing: hasColumnResizing,
    enableDensityToggle: false,
    enableFullScreenToggle: false,
    enablePagination: false,
    enableRowSelection: hasRowSelection,
    enableFilters: false,
    enableHiding: false,
    enableRowOrdering: hasRowReordering,
    enableRowDragging: hasRowReordering,
    enableSorting: hasSorting,
    selectAllMode: "all",
    enableColumnActions: false,
    layoutMode: "grid-no-grow",
    displayColumnDefOptions: {
      "mrt-row-actions": {
        muiTableBodyCellProps: {
          align: "right",
          sx: {
            overflow: "visible",
            width: "unset"
          }
        },
        muiTableHeadCellProps: {
          align: "right",
          sx: {
            width: "unset"
          }
        }
      },
      "mrt-row-drag": {
        header: "",
        muiTableBodyCellProps: {
          sx: {
            minWidth: 0,
            width: "auto"
          }
        },
        muiTableHeadCellProps: {
          sx: {
            minWidth: 0,
            width: "auto"
          }
        }
      }
    },
    enableGlobalFilter: false,
    manualFiltering: true,
    manualSorting: true,
    getRowId: getRowId,
    icons: {
      ArrowDownwardIcon: ArrowDownIcon,
      DragHandleIcon: DragIndicatorIcon,
      SyncAltIcon: ArrowUnsortedIcon
    },
    onSortingChange: handleSortingChange,
    onRowSelectionChange: handleRowSelectionChange,
    enableRowActions: hasRowReordering === true || rowActionButtons || rowActionMenuItems ? true : false,
    positionActionsColumn: "last",
    muiTableHeadCellProps: ({
      column
    }) => ({
      className: sorting.find(item => item.id === column.id) ? "isSorted" : "isUnsorted"
    }),
    muiTableBodyRowProps: ({
      table,
      row
    }) => ({
      className: draggingRow?.id === row.id && table.getState().hoveredRow?.id !== row.id ? "isDragging" : table.getState().hoveredRow?.id === row.id && draggingRow?.id !== row.id ? "isDragTarget" : draggingRow?.id === row.id && table.getState().hoveredRow?.id === row.id ? "isDragging isDragTarget" : undefined
    }),
    muiRowDragHandleProps: ({
      table,
      row
    }) => ({
      title: t("table.draghandle.tooltip"),
      "aria-label": t("table.draghandle.arialabel"),
      onKeyDown: event => handleDragHandleKeyDown({
        table,
        row,
        event
      }),
      onBlur: () => {
        resetDraggingAndHoveredRow(table);
      },
      onDragEnd: () => handleDragHandleOnDragEnd(table),
      onDragCapture: () => handleDragHandleOnDragCapture(table),
      sx: {
        padding: odysseyDesignTokens.Spacing1,
        borderRadius: odysseyDesignTokens.BorderRadiusMain,
        "&:focus-visible": {
          boxShadow: `0 0 0 2px ${odysseyDesignTokens.HueNeutralWhite}, 0 0 0 4px ${odysseyDesignTokens.PalettePrimaryMain}`,
          outline: "2px solid transparent",
          outlineOffset: "1px"
        }
      }
    }),
    renderRowActions: ({
      row
    }) => {
      const currentIndex = row.index + (page - 1) * resultsPerPage;
      return _jsxs(Box, {
        sx: {
          display: "flex"
        },
        children: [rowActionButtons?.(row.original), (rowActionMenuItems || hasRowReordering) && _jsxs(MenuButton, {
          ariaLabel: t("table.moreactions.arialabel"),
          buttonVariant: "floating",
          endIcon: _jsx(MoreIcon, {}),
          menuAlignment: "right",
          size: "small",
          children: [rowActionMenuItems && _jsxs(_Fragment, {
            children: [rowActionMenuItems(row.original), _jsx("hr", {})]
          }), _jsxs(MenuItem, {
            isDisabled: currentIndex <= 0,
            onClick: () => updateRowOrder({
              rowId: row.id,
              newIndex: 0
            }),
            children: [_jsx(ArrowTopIcon, {}), " Bring to front"]
          }), _jsxs(MenuItem, {
            isDisabled: currentIndex <= 0,
            onClick: () => updateRowOrder({
              rowId: row.id,
              newIndex: currentIndex <= 0 ? 0 : currentIndex - 1
            }),
            children: [_jsx(ArrowUpIcon, {}), " Bring forward"]
          }), _jsxs(MenuItem, {
            isDisabled: totalRows ? currentIndex >= totalRows - 1 : false,
            onClick: () => updateRowOrder({
              rowId: row.id,
              newIndex: currentIndex + 1
            }),
            children: [_jsx(ArrowDownIcon, {}), " Send backward"]
          }), _jsx(_Fragment, {
            children: totalRows && _jsxs(MenuItem, {
              isDisabled: currentIndex >= totalRows - 1,
              onClick: () => updateRowOrder({
                rowId: row.id,
                newIndex: totalRows
              }),
              children: [_jsx(ArrowBottomIcon, {}), " Send to back"]
            })
          })]
        })]
      });
    }
  });
  const tableSettings = useMemo(() => _jsxs(_Fragment, {
    children: [hasChangeableDensity && _jsx(MenuButton, {
      ariaLabel: "Table density",
      endIcon: _jsx(ListIcon, {}),
      menuAlignment: "right",
      shouldCloseOnSelect: false,
      children: _jsx(_Fragment, {
        children: densityValues.map(value => _jsx(MenuItem, {
          isSelected: density === value,
          onClick: () => setDensity(value),
          children: `${value.charAt(0).toUpperCase()}${value.slice(1)}`
        }, value))
      })
    }), hasColumnVisibility && _jsx(MenuButton, {
      ariaLabel: "Show/hide columns",
      endIcon: _jsx(ShowIcon, {}),
      menuAlignment: "right",
      shouldCloseOnSelect: false,
      children: _jsx(_Fragment, {
        children: columns.filter(column => column.enableHiding !== false).map(column => _jsxs(MenuItem, {
          onClick: () => handleColumnVisibility(column.accessorKey),
          children: [_jsx(_Checkbox, {
            checked: columnVisibility[column.accessorKey] !== false
          }), column.header]
        }, column.accessorKey))
      })
    })]
  }), [columnVisibility, columns, density, hasChangeableDensity, handleColumnVisibility, hasColumnVisibility]);
  return _jsxs(Box, {
    sx: {
      display: "flex",
      flexDirection: "column",
      gap: 4
    },
    children: [_jsx(DataFilters, {
      additionalActions: tableSettings,
      filters: hasFilters ? columns.filter(column => column.enableColumnFilter !== false).map(column => {
        return {
          id: column.accessorKey,
          label: column.header,
          variant: column.filterVariant ?? "text",
          options: column.filterSelectOptions
        };
      }) : undefined,
      hasSearchSubmitButton: hasSearchSubmitButton,
      onChangeFilters: handleFilters,
      onChangeSearch: hasSearch ? handleSearch : undefined,
      searchDelayTime: searchDelayTime
    }), _jsx(MRT_TableContainer, {
      table: table
    }), hasPagination && _jsx(DataTablePagination, {
      currentNumberOfResults: data.length,
      currentPage: page,
      isNextButtonDisabled: false,
      isPreviousButtonDisabled: page <= 1,
      onClickNext: () => {
        if (paginationType === "loadMore") {
          setResultsPerPage(resultsPerPage + resultsPerPageProp);
        } else {
          setPage(page + 1);
        }
      },
      onClickPrevious: () => setPage(page - 1),
      paginationType: paginationType
    })]
  });
};
const MemoizedDataTable = memo(DataTable);
MemoizedDataTable.displayName = "DataTable";
export { MemoizedDataTable as DataTable };
//# sourceMappingURL=DataTable.js.map