import React from "react";
import { useMultipleSelection, useSelect } from "downshift";
import {
  getMultiOptionsFilter,
  SelectMultiAux,
  SubProps,
} from ":/components/Forms/Select/multi-common";
import { optionToString } from ":/components/Forms/Select/mono-common";

export const SelectMultiSimple = (props: SubProps) => {
  const options = React.useMemo(
    () => props.options.filter(getMultiOptionsFilter(props.selectedItems, "")),
    [props.selectedItems],
  );

  const useMultipleSelectionReturn = useMultipleSelection({
    selectedItems: props.selectedItems,
    onStateChange({ selectedItems: newSelectedItems, type }) {
      switch (type) {
        case useMultipleSelection.stateChangeTypes.SelectedItemKeyDownBackspace:
        case useMultipleSelection.stateChangeTypes.SelectedItemKeyDownDelete:
        case useMultipleSelection.stateChangeTypes.DropdownKeyDownBackspace:
        case useMultipleSelection.stateChangeTypes.FunctionRemoveSelectedItem:
          props.onSelectedItemsChange(newSelectedItems ?? []);
          break;
        default:
          break;
      }
    },
  });

  const downshiftReturn = useSelect({
    items: options,
    itemToString: optionToString,
    selectedItem: null, // Important, without this we are not able to re-select the last removed option.
    defaultHighlightedIndex: 0, // after selection, highlight the first item.
    stateReducer: (state, actionAndChanges) => {
      const { changes, type } = actionAndChanges;
      switch (type) {
        case useSelect.stateChangeTypes.ToggleButtonKeyDownEnter:
        case useSelect.stateChangeTypes.ToggleButtonKeyDownSpaceButton:
        case useSelect.stateChangeTypes.ItemClick:
          return {
            ...changes,
            isOpen: true, // keep the menu open after selection.
            highlightedIndex: 0, // with the first option highlighted.
          };
      }
      return changes;
    },
    onStateChange: ({ type, selectedItem: newSelectedItem }) => {
      switch (type) {
        case useSelect.stateChangeTypes.ToggleButtonKeyDownEnter:
        case useSelect.stateChangeTypes.ToggleButtonKeyDownSpaceButton:
        case useSelect.stateChangeTypes.ItemClick:
          if (newSelectedItem) {
            props.onSelectedItemsChange([
              ...props.selectedItems,
              newSelectedItem,
            ]);
          }
          break;
        default:
          break;
      }
    },
    isItemDisabled: (item) => !!item.disabled,
  });

  return (
    <SelectMultiAux
      {...props}
      options={options}
      labelAsPlaceholder={props.selectedItems.length === 0}
      selectedItems={props.selectedItems}
      downshiftReturn={{
        ...downshiftReturn,
        wrapperProps: {
          onClick: () => {
            if (!props.disabled) {
              downshiftReturn.toggleMenu();
            }
          },
        },
        toggleButtonProps: downshiftReturn.getToggleButtonProps({
          ...useMultipleSelectionReturn.getDropdownProps({
            preventKeyAction: downshiftReturn.isOpen,
          }),
          disabled: props.disabled,
          onClick: (e: React.MouseEvent): void => {
            // As the wrapper also has an onClick handler, we need to stop the event propagation here on it will toggle
            // twice the menu opening which will ... do nothing :).
            e.stopPropagation();
          },
        }),
      }}
      useMultipleSelectionReturn={useMultipleSelectionReturn}
    />
  );
};
