import _extends from "@babel/runtime/helpers/esm/extends";
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
import React, { useState, useRef, useCallback } from 'react';
import PropTypes from 'prop-types';
import pick from 'lodash/pick';
import Input from '../Input';
import { useClassNames, useControlled, PLACEMENT, mergeRefs } from '../utils';
import { animationPropTypes } from '../Animation/utils';
import { PickerToggleTrigger, onMenuKeyDown, DropdownMenu, DropdownMenuItem, PickerOverlay, useFocusItemValue, usePublicMethods, pickTriggerPropKeys } from '../Picker';
import { transformData, shouldDisplay } from './utils';
var defaultProps = {
  as: 'div',
  classPrefix: 'auto-complete',
  defaultValue: '',
  placement: 'bottomStart',
  selectOnEnter: true
};
var AutoComplete = /*#__PURE__*/React.forwardRef(function (props, ref) {
  var Component = props.as,
      disabled = props.disabled,
      className = props.className,
      placement = props.placement,
      selectOnEnter = props.selectOnEnter,
      classPrefix = props.classPrefix,
      defaultValue = props.defaultValue,
      data = props.data,
      valueProp = props.value,
      open = props.open,
      style = props.style,
      menuClassName = props.menuClassName,
      id = props.id,
      renderMenu = props.renderMenu,
      renderMenuItem = props.renderMenuItem,
      onSelect = props.onSelect,
      filterBy = props.filterBy,
      onKeyDown = props.onKeyDown,
      onChange = props.onChange,
      onClose = props.onClose,
      onOpen = props.onOpen,
      onFocus = props.onFocus,
      onBlur = props.onBlur,
      onMenuFocus = props.onMenuFocus,
      rest = _objectWithoutPropertiesLoose(props, ["as", "disabled", "className", "placement", "selectOnEnter", "classPrefix", "defaultValue", "data", "value", "open", "style", "menuClassName", "id", "renderMenu", "renderMenuItem", "onSelect", "filterBy", "onKeyDown", "onChange", "onClose", "onOpen", "onFocus", "onBlur", "onMenuFocus"]);

  var datalist = transformData(data);

  var _useControlled = useControlled(valueProp, defaultValue),
      value = _useControlled[0],
      setValue = _useControlled[1];

  var _useState = useState(false),
      focus = _useState[0],
      setFocus = _useState[1];

  var items = (datalist === null || datalist === void 0 ? void 0 : datalist.filter(shouldDisplay(filterBy, value))) || [];
  var hasItems = items.length > 0;
  var overlayRef = useRef(null); // Used to hover the focuse item  when trigger `onKeydown`

  var _useFocusItemValue = useFocusItemValue(value, {
    data: datalist,
    callback: onMenuFocus,
    target: function target() {
      return overlayRef.current;
    }
  }),
      focusItemValue = _useFocusItemValue.focusItemValue,
      setFocusItemValue = _useFocusItemValue.setFocusItemValue,
      handleKeyDown = _useFocusItemValue.onKeyDown;

  var handleKeyDownEvent = function handleKeyDownEvent(event) {
    if (!overlayRef.current) {
      return;
    }

    onMenuKeyDown(event, {
      enter: selectOnEnter ? selectFocusMenuItem : undefined,
      esc: handleClose
    });
    handleKeyDown(event);
    onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(event);
  };

  var selectFocusMenuItem = function selectFocusMenuItem(event) {
    if (!focusItemValue) {
      return;
    }

    var focusItem = datalist.find(function (item) {
      return (item === null || item === void 0 ? void 0 : item.value) === focusItemValue;
    });
    setValue(focusItemValue);
    setFocusItemValue(focusItemValue);
    handleSelect(focusItem, event);

    if (value !== focusItemValue) {
      handleChangeValue(focusItemValue, event);
    }

    handleClose();
  };

  var handleSelect = useCallback(function (item, event) {
    onSelect === null || onSelect === void 0 ? void 0 : onSelect(item.value, item, event);
  }, [onSelect]);
  var handleChangeValue = useCallback(function (value, event) {
    onChange === null || onChange === void 0 ? void 0 : onChange(value, event);
  }, [onChange]);

  var handleChange = function handleChange(value, event) {
    setFocusItemValue('');
    setValue(value);
    setFocus(true);
    handleChangeValue(value, event);
  };

  var handleClose = useCallback(function () {
    setFocus(false);
    onClose === null || onClose === void 0 ? void 0 : onClose();
  }, [onClose]);
  var handleOpen = useCallback(function () {
    setFocus(true);
    onOpen === null || onOpen === void 0 ? void 0 : onOpen();
  }, [onOpen]);
  var handleItemSelect = useCallback(function (nextItemValue, item, event) {
    setValue(nextItemValue);
    setFocusItemValue(nextItemValue);
    handleSelect(item, event);

    if (value !== nextItemValue) {
      handleChangeValue(nextItemValue, event);
    }

    handleClose();
  }, [value, setValue, handleSelect, handleChangeValue, handleClose, setFocusItemValue]);
  var handleInputFocus = useCallback(function (event) {
    onFocus === null || onFocus === void 0 ? void 0 : onFocus(event);
    handleOpen();
  }, [onFocus, handleOpen]);
  var handleInputBlur = useCallback(function (event) {
    setTimeout(handleClose, 300);
    onBlur === null || onBlur === void 0 ? void 0 : onBlur(event);
  }, [onBlur, handleClose]);

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

  var classes = merge(className, withClassPrefix({
    disabled: disabled
  }));
  var triggerRef = useRef();
  usePublicMethods(ref, {
    triggerRef: triggerRef,
    overlayRef: overlayRef
  });

  var renderDropdownMenu = function renderDropdownMenu(positionProps, speakerRef) {
    var left = positionProps.left,
        top = positionProps.top,
        className = positionProps.className;
    var styles = {
      left: left,
      top: top
    };
    var menu = /*#__PURE__*/React.createElement(DropdownMenu, {
      id: id ? id + "-listbox" : undefined,
      classPrefix: "auto-complete-menu",
      dropdownMenuItemClassPrefix: "auto-complete-item",
      dropdownMenuItemAs: DropdownMenuItem,
      focusItemValue: focusItemValue,
      onSelect: handleItemSelect,
      renderMenuItem: renderMenuItem,
      data: items,
      className: menuClassName
    });
    return /*#__PURE__*/React.createElement(PickerOverlay, {
      ref: mergeRefs(overlayRef, speakerRef),
      style: styles,
      className: className,
      onKeyDown: handleKeyDownEvent,
      target: triggerRef
    }, renderMenu ? renderMenu(menu) : menu);
  };

  return /*#__PURE__*/React.createElement(PickerToggleTrigger, {
    ref: triggerRef,
    placement: placement,
    pickerProps: pick(props, pickTriggerPropKeys),
    trigger: ['click', 'focus'],
    open: open || focus && hasItems,
    speaker: renderDropdownMenu
  }, /*#__PURE__*/React.createElement(Component, {
    className: classes,
    style: style
  }, /*#__PURE__*/React.createElement(Input, _extends({}, rest, {
    id: id,
    disabled: disabled,
    value: value,
    onBlur: handleInputBlur,
    onFocus: handleInputFocus,
    onChange: handleChange,
    onKeyDown: handleKeyDownEvent
  }))));
});
AutoComplete.displayName = 'AutoComplete';
AutoComplete.defaultProps = defaultProps;
AutoComplete.propTypes = _extends({}, animationPropTypes, {
  data: PropTypes.array,
  disabled: PropTypes.bool,
  onSelect: PropTypes.func,
  onChange: PropTypes.func,
  classPrefix: PropTypes.string,
  value: PropTypes.string,
  defaultValue: PropTypes.string,
  className: PropTypes.string,
  menuClassName: PropTypes.string,
  placement: PropTypes.oneOf(PLACEMENT),
  onFocus: PropTypes.func,
  onMenuFocus: PropTypes.func,
  onBlur: PropTypes.func,
  onKeyDown: PropTypes.func,
  onOpen: PropTypes.func,
  onClose: PropTypes.func,
  renderMenu: PropTypes.func,
  renderMenuItem: PropTypes.func,
  style: PropTypes.object,
  open: PropTypes.bool,
  selectOnEnter: PropTypes.bool,
  filterBy: PropTypes.func
});
export default AutoComplete;