import React, { useState, useRef, useCallback } from 'react';
import { useReactTable, getCoreRowModel } from '@tanstack/react-table';
import classnames from 'classnames';
import { faGear } from '@fortawesome/free-solid-svg-icons/faGear';
import { faRotateLeft } from '@fortawesome/free-solid-svg-icons/faRotateLeft';
import { faMagnifyingGlass } from '@fortawesome/free-solid-svg-icons/faMagnifyingGlass';
import { Dropdown, DROPDOWN_PLACEMENT_TYPES } from '../../../dropdown';
import { ACCENT_TYPES, Button } from '../../../button';
import { Input } from '../../../input';
import { useTranslation } from '../../../hooks/use-translation';
import { TableSettingsGroup } from './table-settings-group';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
const minSearchCount = 10;
export function TableSettings({
  tableModel,
  baseColumns,
  defaultState,
  tableContainerWidth,
  enableSorting,
  enablePinning,
  localizationText
}) {
  const {
    t
  } = useTranslation();
  const defaultTranslations = {
    cancelText: t('Cancel'),
    applyText: t('Apply'),
    restToDefaultText: t('Reset to default'),
    searchText: t('Search'),
    titleText: t('Column management'),
    settingsText: t('Settings'),
    noResultText: t('No search results found.'),
    disabledPinText: t('Pinned columns will take too much space with current column pinned'),
    settingsPinnedGroupName: t('Pinned columns'),
    settingsUnPinnedGroupName: t('Unpinned columns'),
    settingsItemPinnedAriaLabel: t('Pin column'),
    settingsItemSortAriaLabel: t('Sort column'),
    settingsColumnItemAriaLabel: t('Use arrow keys to reorder columns. Use Tab key to navigate to inner controls'),
    searchFieldAriaLabel: t('Settings search')
  };
  const localizationTextWithDefault = localizationText ?? defaultTranslations;
  // these refs are used for accessibility improvements, and do not alter components logic. Feel free to ignore when reading =)
  const shouldFocusOnFirstElementRef = useRef(false);
  const [columnOrder, setColumnOrder] = useState(tableModel.getState()?.columnOrder?.length ? tableModel.getState()?.columnOrder : baseColumns.map(column => column.id || column.accessorKey));
  const settings = useReactTable({
    state: {
      columnOrder
    },
    getCoreRowModel: getCoreRowModel(),
    onColumnOrderChange: setColumnOrder,
    columns: baseColumns,
    enableSorting,
    enablePinning,
    sortDescFirst: true,
    data: []
  });
  const [search, setSearch] = useState('');
  const columns = [...settings.getLeftLeafColumns(), ...settings.getCenterLeafColumns()];
  const activeColumns = columns.filter(({
    columnDef
  }) => !columnDef.meta?.hideFromSettings);
  const searchedColumns = activeColumns.filter(({
    columnDef
  }) => {
    const searchableValue = typeof columnDef.header === 'string' ? columnDef.header.toLowerCase() : '';
    return searchableValue.includes(search.toLowerCase());
  });
  const columnGroups = {
    pinned: [],
    unpinned: []
  };
  searchedColumns.forEach(column => {
    if (column.getIsPinned()) {
      columnGroups.pinned.push(column);
    } else {
      columnGroups.unpinned.push(column);
    }
  });
  const setCurrentState = () => {
    setSearch('');
    settings.setState(tableModel.getState());
  };
  const apply = () => {
    tableModel.setColumnVisibility(settings.getState().columnVisibility);
    tableModel.setColumnPinning(settings.getState().columnPinning);
    tableModel.setSorting(settings.getState().sorting);
    tableModel.setColumnOrder(settings.getState().columnOrder);
  };
  const resetToDefault = () => {
    tableModel.setColumnVisibility(defaultState.visible || {});
    tableModel.setColumnPinning(defaultState.pinned || {});
    tableModel.setSorting(defaultState.sorting || []);
    tableModel.setColumnSizing(defaultState.columnSizing || {});
    tableModel.setRowSelection(defaultState.selected || {});
    tableModel.setExpanded(defaultState.expandedRows || {});
    const defaultColumnOrder = baseColumns.map(column => column.id || column.accessorKey);
    tableModel.setColumnOrder(defaultColumnOrder);
    setColumnOrder(defaultColumnOrder);
  };
  const handleColumnsReorder = (newItems, previousIndex, currentIndex) => {
    const draggedItem = newItems[currentIndex];
    const hoveredItem = newItems[previousIndex];

    // if we are reordering pinned items - just rewrite the whole array with the right order
    if (draggedItem.getIsPinned()) {
      settings.setColumnPinning(prevState => {
        return {
          ...prevState,
          left: newItems.map(item => item.id)
        };
      });
    } else {
      // now we need to find respective indexes in the columnsOrder array as it may differ from this one due to pinned and reserved columns
      const dragIndex = columnOrder.findIndex(columnItem => columnItem === draggedItem.id);
      const hoverIndex = columnOrder.findIndex(columnItem => columnItem === hoveredItem.id);
      settings.setColumnOrder(prevState => {
        const newState = [...prevState];
        newState.splice(dragIndex, 1);
        newState.splice(hoverIndex, 0, draggedItem.id);
        return newState;
      });
    }
  };
  const handleKeyboardColumnsReorder = (currentIndex, nextIndex, movedColumn) => {
    if (movedColumn.getIsPinned() && nextIndex >= 0 && nextIndex < columnGroups.pinned.length) {
      settings.setColumnPinning(prevState => {
        const pinnedGroup = [...columnGroups.pinned];
        pinnedGroup.splice(currentIndex, 1);
        pinnedGroup.splice(nextIndex, 0, movedColumn);
        return {
          ...prevState,
          left: pinnedGroup.map(i => i.id)
        };
      });
    } else if (nextIndex < columnGroups.unpinned.length && nextIndex >= 0) {
      const hoveredItem = columnGroups.unpinned[nextIndex];
      // now we need to find respective indexes in the columnsOrder array as it may differ from this one due to pinned and reserved columns
      const dragIndex = columnOrder.findIndex(columnItem => columnItem === movedColumn.id);
      const hoverIndex = columnOrder.findIndex(columnItem => columnItem === hoveredItem.id);
      settings.setColumnOrder(prevState => {
        const newState = [...prevState];
        newState.splice(dragIndex, 1);
        newState.splice(hoverIndex, 0, movedColumn.id);
        return newState;
      });
    }
  };

  // this is ref callback to focus on first input element when dropdown is opened via keyboard
  const focusOnFirstInput = useCallback(element => {
    if (element && shouldFocusOnFirstElementRef.current) {
      // if search is shown - focus on it first
      if (activeColumns.length >= minSearchCount) {
        element.querySelector('.table-settings input').focus();
      } else {
        // if there is no search - focus on first column container
        element.querySelector('[test-id="table-settings-column-container"]').focus();
      }
      shouldFocusOnFirstElementRef.current = false;
    }
  }, [activeColumns.length]);
  return /*#__PURE__*/_jsx(Dropdown, {
    placement: DROPDOWN_PLACEMENT_TYPES.BOTTOM_START,
    hasCustomFocusHandling: true,
    renderAnchor: ({
      ref,
      onClick,
      isOpen
    }) => /*#__PURE__*/_jsx(Button, {
      ref: ref,
      onClick: e => {
        // e.detail stores number of clicks, so 0 means there was no clicks, hence - it's a keyboard initiated click
        // more info: https://developer.mozilla.org/en-US/docs/Web/API/UIEvent/detail
        const isOpenedWithKeyboard = e.detail === 0;
        setCurrentState();
        onClick(e, isOpenedWithKeyboard);
      },
      className: classnames(isOpen && 'active'),
      onKeyDown: e => {
        if (e.key === ' ' || e.key === 'Enter') {
          // if we opened dropdown via keyboard click - we need to focus on the first element
          shouldFocusOnFirstElementRef.current = true;
        }
      },
      testId: "table-settings",
      leftIcon: faGear,
      accentType: ACCENT_TYPES.GHOST,
      children: localizationTextWithDefault.settingsText
    }),
    shouldCloseDropdownOnEsc: true,
    contentClassName: "table-react-settings-container",
    children: ({
      closeDropdown
    }) => /*#__PURE__*/_jsxs("div", {
      className: "table-settings",
      "test-id": "table-settings-container",
      ref: focusOnFirstInput,
      children: [/*#__PURE__*/_jsx("p", {
        className: "table-settings-title",
        children: localizationTextWithDefault.titleText
      }), activeColumns.length >= minSearchCount ? /*#__PURE__*/_jsx(Input, {
        leftIcon: faMagnifyingGlass,
        placeholder: localizationTextWithDefault.searchText,
        className: "table-settings-search",
        value: search,
        onChange: e => setSearch(e.target.value),
        "aria-label": localizationTextWithDefault.searchFieldAriaLabel
      }) : null, /*#__PURE__*/_jsxs("div", {
        className: "table-settings-columns",
        children: [columnGroups.pinned.length > 0 ? /*#__PURE__*/_jsx(TableSettingsGroup, {
          groupId: "pinned",
          groupName: localizationTextWithDefault.settingsPinnedGroupName,
          settings: settings,
          columns: columnGroups.pinned,
          tableContainerWidth: tableContainerWidth,
          onItemMove: handleColumnsReorder,
          handleKeyboardColumnsReorder: handleKeyboardColumnsReorder,
          isReorderEnabled: search === '',
          localizationText: localizationTextWithDefault
        }) : null, columnGroups.unpinned.length > 0 ? /*#__PURE__*/_jsx(TableSettingsGroup, {
          groupId: "unpinned",
          groupName: localizationTextWithDefault.settingsUnPinnedGroupName,
          settings: settings,
          columns: columnGroups.unpinned,
          tableContainerWidth: tableContainerWidth,
          onItemMove: handleColumnsReorder,
          handleKeyboardColumnsReorder: handleKeyboardColumnsReorder,
          isReorderEnabled: search === '',
          localizationText: localizationTextWithDefault
        }) : null, !searchedColumns.length && search && /*#__PURE__*/_jsx("p", {
          className: "table-settings-no-result",
          children: localizationTextWithDefault.noResultText
        })]
      }), /*#__PURE__*/_jsx("div", {
        className: "table-settings-reset",
        children: /*#__PURE__*/_jsx(Button, {
          className: "table-settings-actions-button",
          accentType: ACCENT_TYPES.GHOST,
          leftIcon: faRotateLeft,
          testId: "reset-settings",
          fullWidth: true,
          onClick: () => {
            resetToDefault();
            closeDropdown();
          },
          children: localizationTextWithDefault.restToDefaultText
        })
      }), /*#__PURE__*/_jsxs("div", {
        className: "table-settings-actions",
        children: [/*#__PURE__*/_jsx(Button, {
          className: "table-settings-actions-button",
          accentType: ACCENT_TYPES.SECONDARY,
          onClick: closeDropdown,
          testId: "cancel-settings",
          children: localizationTextWithDefault.cancelText
        }), /*#__PURE__*/_jsx(Button, {
          className: "table-settings-actions-button",
          accentType: ACCENT_TYPES.PRIMARY,
          testId: "apply-settings",
          onClick: () => {
            apply();
            closeDropdown();
          },
          children: localizationTextWithDefault.applyText
        })]
      })]
    })
  });
}