import { useCallback, useMemo } from 'react';

import { assertUnreachable } from '../../../utils/assertUnreachable';
import { TableSelectionType } from '../constants';
import { useTablePropsContext } from '../contexts/TablePropsContext';
import { useTableSelectionContext } from '../contexts/TableSelectionContext';

/** Result of {@link useAllRowsSelection} hook. */
export interface UseAllRowsSelectionResult {
  /** Flag indicating whether all rows on current page are selected. */
  isAllRowsSelected: boolean;
  /** Function that will toggle all rows on current page selection. */
  onAllRowsSelectionChange: (selected: boolean) => void;
}

/** Hook that returns information about all rows in current page selection. */
export function useAllRowsSelection(): UseAllRowsSelectionResult {
  const { selection, onSelectionChanged } = useTableSelectionContext();
  const { totalRows } = useTablePropsContext();

  const onAllRowsSelectionChange = useCallback(
    (selected: boolean) => {
      if (selected) {
        onSelectionChanged &&
          onSelectionChanged({
            type: TableSelectionType.Exclude,
            unselectedIds: [],
          });
      } else {
        onSelectionChanged &&
          onSelectionChanged({
            type: TableSelectionType.Include,
            selectedIds: [],
          });
      }
    },
    [onSelectionChanged],
  );

  const isAllRowsSelected = useMemo(() => {
    if (!selection) {
      return false;
    }

    switch (selection.type) {
      case TableSelectionType.Exclude:
        return selection.unselectedIds.size === 0;
      case TableSelectionType.Include:
        return selection.selectedIds.size === totalRows;
      /* istanbul ignore next */
      default:
        assertUnreachable(selection);
    }
  }, [selection, totalRows]);

  return {
    onAllRowsSelectionChange,
    isAllRowsSelected,
  };
}
