import _taggedTemplateLiteralLoose from "@babel/runtime/helpers/esm/taggedTemplateLiteralLoose";
import _extends from "@babel/runtime/helpers/esm/extends";
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";

function _templateObject() {
  var data = _taggedTemplateLiteralLoose(["none"]);

  _templateObject = function _templateObject() {
    return data;
  };

  return data;
}

import React, { useRef, useState, useCallback } from 'react';
import PropTypes from 'prop-types';
import clone from 'lodash/clone';
import isUndefined from 'lodash/isUndefined';
import isFunction from 'lodash/isFunction';
import remove from 'lodash/remove';
import omit from 'lodash/omit';
import pick from 'lodash/pick';
import isNil from 'lodash/isNil';
import { filterNodesOfTree } from '../utils/treeUtils';
import { createChainedFunction, getDataGroupBy, useClassNames, shallowEqual, useCustom, useControlled, mergeRefs } from '../utils';
import { DropdownMenu, DropdownMenuCheckItem as DropdownMenuItem, PickerToggle, PickerOverlay, SearchBar, SelectedElement, PickerToggleTrigger, useFocusItemValue, usePickerClassName, useSearch, usePublicMethods, useToggleKeyDownEvent, pickTriggerPropKeys, omitTriggerPropKeys, listPickerPropTypes } from '../Picker';
var defaultProps = {
  as: 'div',
  appearance: 'default',
  classPrefix: 'picker',
  countable: true,
  searchable: true,
  cleanable: true,
  data: [],
  disabledItemValues: [],
  valueKey: 'value',
  labelKey: 'label',
  placement: 'bottomStart',
  menuAutoWidth: true,
  menuMaxHeight: 320
};
var CheckPicker = /*#__PURE__*/React.forwardRef(function (props, ref) {
  var Component = props.as,
      classPrefix = props.classPrefix,
      countable = props.countable,
      data = props.data,
      disabledItemValues = props.disabledItemValues,
      valueKey = props.valueKey,
      labelKey = props.labelKey,
      searchable = props.searchable,
      virtualized = props.virtualized,
      cleanable = props.cleanable,
      placement = props.placement,
      menuAutoWidth = props.menuAutoWidth,
      menuMaxHeight = props.menuMaxHeight,
      menuClassName = props.menuClassName,
      menuStyle = props.menuStyle,
      overrideLocale = props.locale,
      placeholder = props.placeholder,
      disabled = props.disabled,
      toggleAs = props.toggleAs,
      style = props.style,
      sticky = props.sticky,
      valueProp = props.value,
      defaultValue = props.defaultValue,
      groupBy = props.groupBy,
      listProps = props.listProps,
      id = props.id,
      sort = props.sort,
      searchBy = props.searchBy,
      renderMenuItem = props.renderMenuItem,
      renderMenuGroup = props.renderMenuGroup,
      renderValue = props.renderValue,
      renderExtraFooter = props.renderExtraFooter,
      renderMenu = props.renderMenu,
      onGroupTitleClick = props.onGroupTitleClick,
      onSearch = props.onSearch,
      onEnter = props.onEnter,
      onEntered = props.onEntered,
      onExited = props.onExited,
      onClean = props.onClean,
      onChange = props.onChange,
      onSelect = props.onSelect,
      onClose = props.onClose,
      onOpen = props.onOpen,
      rest = _objectWithoutPropertiesLoose(props, ["as", "classPrefix", "countable", "data", "disabledItemValues", "valueKey", "labelKey", "searchable", "virtualized", "cleanable", "placement", "menuAutoWidth", "menuMaxHeight", "menuClassName", "menuStyle", "locale", "placeholder", "disabled", "toggleAs", "style", "sticky", "value", "defaultValue", "groupBy", "listProps", "id", "sort", "searchBy", "renderMenuItem", "renderMenuGroup", "renderValue", "renderExtraFooter", "renderMenu", "onGroupTitleClick", "onSearch", "onEnter", "onEntered", "onExited", "onClean", "onChange", "onSelect", "onClose", "onOpen"]);

  var triggerRef = useRef();
  var targetRef = useRef();
  var overlayRef = useRef();

  var _useCustom = useCustom('Picker', overrideLocale),
      locale = _useCustom.locale;

  var _useControlled = useControlled(valueProp, defaultValue || []),
      value = _useControlled[0],
      setValue = _useControlled[1]; // Used to hover the focuse item  when trigger `onKeydown`


  var _useFocusItemValue = useFocusItemValue(value === null || value === void 0 ? void 0 : value[0], {
    data: data,
    valueKey: valueKey,
    target: function target() {
      return overlayRef.current;
    }
  }),
      focusItemValue = _useFocusItemValue.focusItemValue,
      setFocusItemValue = _useFocusItemValue.setFocusItemValue,
      onFocusItem = _useFocusItemValue.onKeyDown;

  var handleSearchCallback = useCallback(function (searchKeyword, filteredData, event) {
    var _filteredData$;

    // The first option after filtering is the focus.
    setFocusItemValue(filteredData === null || filteredData === void 0 ? void 0 : (_filteredData$ = filteredData[0]) === null || _filteredData$ === void 0 ? void 0 : _filteredData$[valueKey]);
    onSearch === null || onSearch === void 0 ? void 0 : onSearch(searchKeyword, event);
  }, [setFocusItemValue, onSearch, valueKey]); // Use search keywords to filter options.

  var _useSearch = useSearch({
    labelKey: labelKey,
    data: data,
    searchBy: searchBy,
    callback: handleSearchCallback
  }),
      searchKeyword = _useSearch.searchKeyword,
      filteredData = _useSearch.filteredData,
      setSearchKeyword = _useSearch.setSearchKeyword,
      handleSearch = _useSearch.handleSearch,
      checkShouldDisplay = _useSearch.checkShouldDisplay; // Use component active state to support keyboard events.


  var _useState = useState(false),
      active = _useState[0],
      setActive = _useState[1]; // A list of shortcut options.
  // when opened again, the selected options are displayed at the top.


  var _useState2 = useState([]),
      stickyItems = _useState2[0],
      setStickyItems = _useState2[1];

  var initStickyItems = function initStickyItems() {
    if (!sticky) {
      return;
    }

    var nextStickyItems = [];

    if (data && value.length) {
      nextStickyItems = data.filter(function (item) {
        return value.some(function (v) {
          return v === item[valueKey];
        });
      });
    }

    setStickyItems(nextStickyItems);
  };

  var handleChangeValue = useCallback(function (value, event) {
    onChange === null || onChange === void 0 ? void 0 : onChange(value, event);
  }, [onChange]);
  var handleClean = useCallback(function (event) {
    if (disabled || !cleanable) {
      return;
    }

    setValue([]);
    handleChangeValue([], event);
  }, [disabled, cleanable, setValue, handleChangeValue]);

  var handleMenuPressEnter = function handleMenuPressEnter(event) {
    var nextValue = clone(value);

    if (!focusItemValue) {
      return;
    }

    if (!nextValue.some(function (v) {
      return shallowEqual(v, focusItemValue);
    })) {
      nextValue.push(focusItemValue);
    } else {
      remove(nextValue, function (itemVal) {
        return shallowEqual(itemVal, focusItemValue);
      });
    }

    var focusItem = data.find(function (item) {
      return shallowEqual(item === null || item === void 0 ? void 0 : item[valueKey], focusItemValue);
    });
    setValue(nextValue);
    handleSelect(nextValue, focusItem, event);
    handleChangeValue(nextValue, event);
  };

  var onPickerKeyDown = useToggleKeyDownEvent(_extends({
    toggle: !focusItemValue || !active,
    triggerRef: triggerRef,
    targetRef: targetRef,
    overlayRef: overlayRef,
    active: active,
    onExit: handleClean,
    onMenuKeyDown: onFocusItem,
    onMenuPressEnter: handleMenuPressEnter,
    onClose: function onClose() {
      setFocusItemValue(null);
    }
  }, rest));
  var handleSelect = useCallback(function (nextItemValue, item, event) {
    onSelect === null || onSelect === void 0 ? void 0 : onSelect(nextItemValue, item, event);
  }, [onSelect]);
  var handleItemSelect = useCallback(function (nextItemValue, item, event, checked) {
    var nextValue = clone(value);

    if (checked) {
      nextValue.push(nextItemValue);
    } else {
      remove(nextValue, function (itemVal) {
        return shallowEqual(itemVal, nextItemValue);
      });
    }

    setValue(nextValue);
    setFocusItemValue(nextItemValue);
    handleSelect(nextValue, item, event);
    handleChangeValue(nextValue, event);
  }, [value, setValue, handleSelect, handleChangeValue, setFocusItemValue]);
  var handleEntered = useCallback(function () {
    setActive(true);
    onOpen === null || onOpen === void 0 ? void 0 : onOpen();
  }, [onOpen]);
  var handleExited = useCallback(function () {
    setSearchKeyword('');
    setFocusItemValue(null);
    setActive(false);
    onClose === null || onClose === void 0 ? void 0 : onClose();
  }, [onClose, setFocusItemValue, setSearchKeyword]);
  usePublicMethods(ref, {
    triggerRef: triggerRef,
    overlayRef: overlayRef,
    targetRef: targetRef
  });
  var selectedItems = data.filter(function (item) {
    return value === null || value === void 0 ? void 0 : value.some(function (val) {
      return shallowEqual(item[valueKey], val);
    });
  }) || [];
  /**
   * 1.Have a value and the value is valid.
   * 2.Regardless of whether the value is valid, as long as renderValue is set, it is judged to have a value.
   */

  var hasValue = selectedItems.length > 0 || (value === null || value === void 0 ? void 0 : value.length) > 0 && isFunction(renderValue);

  var _useClassNames = useClassNames(classPrefix),
      prefix = _useClassNames.prefix,
      merge = _useClassNames.merge;

  var selectedElement = placeholder;

  if (selectedItems.length > 0) {
    selectedElement = /*#__PURE__*/React.createElement(SelectedElement, {
      selectedItems: selectedItems,
      countable: countable,
      valueKey: valueKey,
      labelKey: labelKey,
      prefix: prefix
    });
  }

  if ((value === null || value === void 0 ? void 0 : value.length) > 0 && isFunction(renderValue)) {
    selectedElement = renderValue(value, selectedItems, selectedElement); // If renderValue returns null or undefined, hasValue is false.

    if (isNil(selectedElement)) {
      hasValue = false;
    }
  }

  var renderDropdownMenu = function renderDropdownMenu(positionProps, speakerRef) {
    var left = positionProps.left,
        top = positionProps.top,
        className = positionProps.className;
    var classes = merge(className, menuClassName, prefix('check-menu'));

    var styles = _extends({}, menuStyle, {
      left: left,
      top: top
    });

    var items = filteredData;
    var filteredStickyItems = [];

    if (stickyItems) {
      filteredStickyItems = filterNodesOfTree(stickyItems, function (item) {
        return checkShouldDisplay(item);
      });
      items = filterNodesOfTree(data, function (item) {
        return checkShouldDisplay(item) && !stickyItems.some(function (v) {
          return v[valueKey] === item[valueKey];
        });
      });
    } // Create a tree structure data when set `groupBy`


    if (groupBy) {
      items = getDataGroupBy(items, groupBy, sort);
    } else if (typeof sort === 'function') {
      items = items.sort(sort(false));
    }

    var menu = items.length || filteredStickyItems.length ? /*#__PURE__*/React.createElement(DropdownMenu, {
      id: id ? id + "-listbox" : undefined,
      listProps: listProps,
      disabledItemValues: disabledItemValues,
      valueKey: valueKey,
      labelKey: labelKey,
      renderMenuGroup: renderMenuGroup,
      renderMenuItem: renderMenuItem,
      maxHeight: menuMaxHeight,
      classPrefix: 'picker-check-menu',
      dropdownMenuItemAs: DropdownMenuItem,
      activeItemValues: value,
      focusItemValue: focusItemValue,
      data: [].concat(filteredStickyItems, items),
      group: !isUndefined(groupBy),
      onSelect: handleItemSelect,
      onGroupTitleClick: onGroupTitleClick,
      virtualized: virtualized
    }) : /*#__PURE__*/React.createElement("div", {
      className: prefix(_templateObject())
    }, locale === null || locale === void 0 ? void 0 : locale.noResultsText);
    return /*#__PURE__*/React.createElement(PickerOverlay, {
      ref: mergeRefs(overlayRef, speakerRef),
      autoWidth: menuAutoWidth,
      className: classes,
      style: styles,
      onKeyDown: onPickerKeyDown,
      target: triggerRef
    }, searchable && /*#__PURE__*/React.createElement(SearchBar, {
      placeholder: locale === null || locale === void 0 ? void 0 : locale.searchPlaceholder,
      onChange: handleSearch,
      value: searchKeyword
    }), renderMenu ? renderMenu(menu) : menu, renderExtraFooter === null || renderExtraFooter === void 0 ? void 0 : renderExtraFooter());
  };

  var _usePickerClassName = usePickerClassName(_extends({}, props, {
    hasValue: hasValue,
    name: 'check'
  })),
      classes = _usePickerClassName[0],
      usedClassNamePropKeys = _usePickerClassName[1];

  return /*#__PURE__*/React.createElement(PickerToggleTrigger, {
    pickerProps: pick(props, pickTriggerPropKeys),
    ref: triggerRef,
    placement: placement,
    onEnter: createChainedFunction(initStickyItems, onEnter),
    onEntered: createChainedFunction(handleEntered, onEntered),
    onExited: createChainedFunction(handleExited, onExited),
    speaker: renderDropdownMenu
  }, /*#__PURE__*/React.createElement(Component, {
    className: classes,
    style: style
  }, /*#__PURE__*/React.createElement(PickerToggle, _extends({}, omit(rest, [].concat(omitTriggerPropKeys, usedClassNamePropKeys)), {
    id: id,
    ref: targetRef,
    disabled: disabled,
    onClean: createChainedFunction(handleClean, onClean),
    onKeyDown: onPickerKeyDown,
    as: toggleAs,
    cleanable: cleanable && !disabled,
    hasValue: hasValue,
    active: active,
    placement: placement,
    inputValue: value
  }), selectedElement || (locale === null || locale === void 0 ? void 0 : locale.placeholder))));
});
CheckPicker.displayName = 'CheckPicker';
CheckPicker.defaultProps = defaultProps;
CheckPicker.propTypes = _extends({}, listPickerPropTypes, {
  locale: PropTypes.any,
  appearance: PropTypes.oneOf(['default', 'subtle']),
  menuAutoWidth: PropTypes.bool,
  menuMaxHeight: PropTypes.number,
  renderMenu: PropTypes.func,
  renderMenuItem: PropTypes.func,
  renderMenuGroup: PropTypes.func,
  onSelect: PropTypes.func,
  onGroupTitleClick: PropTypes.func,
  onSearch: PropTypes.func,
  groupBy: PropTypes.any,
  sort: PropTypes.func,
  searchable: PropTypes.bool,
  countable: PropTypes.bool,
  sticky: PropTypes.bool,
  virtualized: PropTypes.bool,
  searchBy: PropTypes.func
});
export default CheckPicker;