import _extends from "@babel/runtime/helpers/esm/extends";
import _styled from "styled-components";
import React, { useCallback, useState, useEffect, useRef, useMemo, Fragment } from "react";
import { RemoveScroll } from "react-remove-scroll";
import classNames from "classnames";
import { StyledComboBoxCloseSmallIcon, StyledComboBoxCollapseExpandSingleIcon, StyledComboBoxInput, StyledComboBoxList, StyledChipWrapper } from "./Styles";
import { Portal } from "../../helpers";
import { ConditionalWrapper } from "../../helpers/ConditionWrapper/ConditionWrapper";
import { useIsFirstRender } from "../../hooks/useIsFirstRender";
import { useOnClickOutside } from "../../hooks/useOnClickOutside";
import useForkRef from "../../utils/useForkRef";
import { Autocomplete } from "../Autocomplete";
import { isOptionGroup } from "../Autocomplete/Autocomplete";
import { Avatar } from "../Avatar";
import { Checkbox } from "../Checkbox";
import { Chip } from "../Chip";
import { IconButton } from "../IconButton";
import { InputAdornment } from "../Input/InputAdornment";
import { StyledInput, StyledInputWrapper } from "../Input/Styles";
import { SpinnerLoader } from "../Loaders/Spinner/SpinnerLoader";
import { MultiAvatar } from "../MultiAvatar";
import { Popper } from "../Popper";
import { RadioButton } from "../RadioButton";
import { OptionContent } from "../Select/OptionContent/OptionContent";
import { Trigger } from "../Trigger";
import { Typography } from "../Typography/Typography";
const sizeMap = {
  small: 18,
  regular: 24,
  big: 30,
  biggest: 40
};
export const ComboBox = _ref => {
  var _comboBoxRef$current2, _comboBoxRef$current3;
  let {
    options = [],
    selected,
    loading = false,
    loadingText,
    onChange,
    onInputChange,
    placeholder,
    handleEmptyAction,
    disabled = false,
    size = "regular",
    invalid = false,
    type = "single",
    renderChip,
    forceCloseMenu = type === "single",
    renderOption,
    limitChips = 2,
    hiddenNumberText,
    inPortal = false,
    inputWrapperClassName,
    scrollWrapper,
    onClose,
    onClear,
    onDeselect,
    defaultValue,
    open: defaultOpen = false,
    onOpen,
    triggerMode,
    noResultText,
    emptyValue,
    ...prop
  } = _ref;
  const selectedName = useMemo(() => {
    let value = "";
    if (!selected) {
      return value;
    }
    options.map(v => {
      if (v != null && v.options) {
        return v.options.find(q => {
          if (q.id === selected) {
            value = q.name;
            return;
          }
        });
      } else {
        if (v.id === selected) {
          value = v.name;
          return;
        }
      }
    });
    return value;
  }, [options, selected]);
  const [value, setValue] = useState(selectedName);
  const [focused, setFocused] = useState(false);
  const handleOnChange = useCallback(e => {
    setValue(e.target.value);
    onInputChange == null || onInputChange(e.target.value);
  }, [onInputChange]);
  const childNode = useRef();
  const elementRef = useRef(null);
  const handleRef = useForkRef(childNode, elementRef);
  const wrapperRef = useRef(null);
  const chipWrapper = useRef(null);
  const comboBoxRef = useRef(null);
  const [open, setOpen] = useState(defaultOpen);
  const isFirstRender = useIsFirstRender();
  useOnClickOutside(wrapperRef, e => {
    var _comboBoxRef$current;
    if (e.target && (_comboBoxRef$current = comboBoxRef.current) != null && _comboBoxRef$current.contains(e.target)) {
      return;
    }
    setOpen(false);
  });
  const handleOnKeyDown = useCallback(e => {
    if (e.key === "Escape" && open) {
      setOpen(false);
      setValue(selectedName);
      e.stopPropagation();
    }
    if (e.key === "Enter" && type === "multiple") {
      setValue("");
    }
    if (e.key === "Enter" && !open && focused) {
      setOpen(true);
      onOpen == null || onOpen();
    }
  }, [focused, onOpen, open, selectedName, type]);
  useEffect(() => {
    var _childNode$current, _childNode$current2;
    open && (childNode == null || (_childNode$current = childNode.current) == null ? void 0 : _childNode$current.focus());
    !open && (childNode == null || (_childNode$current2 = childNode.current) == null ? void 0 : _childNode$current2.blur());
  }, [childNode, open]);
  useEffect(() => {
    setValue(selectedName);
  }, [selectedName]);
  useEffect(() => {
    if (open !== defaultOpen) setOpen(defaultOpen);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [defaultOpen]);
  useEffect(() => {
    if (!open && !isFirstRender && !focused) {
      if (typeof onClose === "function") {
        onClose();
      }
    }
  }, [focused, isFirstRender, onClose, open]);
  const emptyAction = useCallback(v => {
    handleEmptyAction == null || handleEmptyAction(v);
    setOpen(false);
  }, [handleEmptyAction]);
  const handleChange = useCallback(selectedValue => {
    if (selectedValue !== selected && typeof onChange === "function") {
      onChange(selectedValue);
    }
    if (forceCloseMenu) {
      setOpen(false);
    }
  }, [forceCloseMenu, onChange, selected]);
  const handleOpen = useCallback(() => {
    if (!disabled) {
      setOpen(true);
      onOpen == null || onOpen();
    }
  }, [disabled, onOpen]);
  const handleRenderOption = useCallback((option, props) => {
    if (typeof renderOption === "function") {
      return renderOption(option, props);
    }
    if (type === "multiple") {
      return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(OptionContent, {
        imageUrl: option.image,
        color: option.color,
        textColor: option.textColor,
        name: option.name
      }), /*#__PURE__*/React.createElement(Checkbox, props));
    }
    return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(OptionContent, {
      imageUrl: option.image,
      color: option.color,
      textColor: option.textColor,
      name: option.name
    }), /*#__PURE__*/React.createElement(RadioButton, props));
  }, [type, renderOption]);
  const handleDeselect = useCallback(e => {
    e.stopPropagation();
    if (typeof onDeselect === "function") {
      onDeselect();
    } else if (type === "multiple") {
      onChange == null || onChange([]);
    } else {
      onChange == null || onChange("");
    }
    onClear == null || onClear();
    setOpen(false);
  }, [type, onChange, onClear, onDeselect]);
  const handleMouseDown = useCallback(e => {
    e.preventDefault();
  }, []);
  const handleBlur = useCallback(() => {
    setValue(selectedName);
    setFocused(!focused);
  }, [focused, selectedName]);
  const renderChipAdornment = useCallback((option, index) => {
    if (typeof renderChip === "function") {
      return renderChip(option, index);
    }
    const avatarProps = {
      size: 18
    };
    switch (size) {
      case "big":
        avatarProps.size = 22;
        break;
      case "small":
        avatarProps.size = 14;
        break;
    }
    const startAdornment = option.image ? /*#__PURE__*/React.createElement(_StyledAvatar, _extends({
      url: option.image
    }, avatarProps, {
      $_css: {
        "marginTop": "0.125rem",
        "marginBottom": "0.125rem"
      },
      $_css2: {
        "marginRight": "0.125rem"
      }
    })) : undefined;
    const onClose = e => {
      e.preventDefault();
      e.stopPropagation();
      if (Array.isArray(selected) && selected.includes(option.id)) {
        if (typeof onChange === "function") {
          const newSelected = selected.filter(item => item !== option.id);
          onChange(newSelected);
        }
      }
    };
    let showOnClose = true;
    if (disabled) {
      showOnClose = false;
    }
    if (option.color) {
      showOnClose = false;
    }
    return /*#__PURE__*/React.createElement(Chip, {
      className: "c-combo-box-chip",
      startAdornment: startAdornment,
      label: option.name,
      key: index,
      backgroundColor: option.color,
      color: option.chipColor,
      onClose: showOnClose ? onClose : undefined,
      size: size
    });
  }, [disabled, onChange, renderChip, selected, size]);
  const autoSize = useMemo(() => {
    if (type === "multiple" && open && Array.isArray(selected) && selected.length > 1) {
      return "auto";
    }
    return size;
  }, [open, selected, size, type]);
  const startAdornment = useMemo(() => {
    if (type === "multiple" && Array.isArray(selected) && selected.length > 0) {
      const elements = [];
      let total = 0;
      options.forEach((option, index) => {
        const isGrouped = isOptionGroup(option);
        if (selected.includes(option.id) && !isGrouped) {
          total = total + 1;
          elements.push(renderChipAdornment(option, index));
        } else if (isGrouped) {
          const groupedOptions = option.options.filter(o => selected.includes(o.id));
          total = total + groupedOptions.length;
          if (groupedOptions.length > 0) {
            groupedOptions.forEach((o, _index) => {
              elements.push(renderChipAdornment(o, index + "_" + _index));
            });
          }
        }
      });
      let hidden = 0;
      if (!open && limitChips > 0 && elements.length > limitChips) {
        hidden = elements.splice(limitChips, elements.length - limitChips).length;
      }
      return /*#__PURE__*/React.createElement(Fragment, null, elements, hidden > 0 && /*#__PURE__*/React.createElement(_StyledTypography, {
        variant: size === "small" ? "Caption 1" : size === "regular" ? "Body 2" : "Body 1"
      }, typeof hiddenNumberText === "function" ? hiddenNumberText(hidden) : "+" + hidden));
    }
    if (type === "single" && selected) {
      let optionItem;
      options.forEach(option => {
        if (isOptionGroup(option)) {
          optionItem = option.options.find(child => child.id === selected);
        } else if (!optionItem && option.id === selected) {
          optionItem = option;
        }
      });
      if (optionItem && optionItem.image) {
        const avatarSize = size === "big" ? 22 : size === "regular" ? 18 : 14;
        if (Array.isArray(optionItem.image)) {
          return /*#__PURE__*/React.createElement(MultiAvatar, {
            url: optionItem.image,
            size: avatarSize
          });
        }
        return /*#__PURE__*/React.createElement(Avatar, {
          url: optionItem.image,
          size: avatarSize
        });
      }
    }
    return undefined;
  }, [type, selected, options, open, limitChips, hiddenNumberText, renderChipAdornment, size]);
  const showXIcon = Array.isArray(selected) && type === "multiple" && selected.length > 0;
  const hasSelected = type === "multiple" && Array.isArray(selected) && selected.length > 0;
  const showMenu = useMemo(() => {
    const hasOptions = (options == null ? void 0 : options.length) > 0;
    const valueExists = option => option.id.toString().includes(value) || option.name.includes(value);
    const isValueInOptions = options == null ? void 0 : options.some(option => isOptionGroup(option) ? option.options.some(valueExists) : valueExists(option));
    return hasOptions && (!!defaultValue || !value) || value && (isValueInOptions || emptyValue || noResultText);
  }, [defaultValue, emptyValue, noResultText, options, value]);
  return /*#__PURE__*/React.createElement("div", {
    className: "c-combo-box"
  }, type === "multiple" ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(_StyledStyledInputWrapper, {
    $disabled: disabled,
    $size: size,
    $invalid: invalid,
    ref: comboBoxRef,
    className: classNames("c-combo-box-input-wrapper", inputWrapperClassName),
    onClick: () => {
      var _elementRef$current;
      (_elementRef$current = elementRef.current) == null || _elementRef$current.click();
    },
    $_css3: autoSize === "auto" ? "auto" : undefined,
    $_css4: autoSize === "auto" && scrollWrapper ? "scroll" : undefined
  }, /*#__PURE__*/React.createElement(_StyledStyledChipWrapper, {
    $autoSize: autoSize,
    $open: open,
    ref: chipWrapper,
    $_css5: autoSize === "auto" && scrollWrapper ? sizeMap[size] * 3 + 8 + "px" : undefined
  }, startAdornment, /*#__PURE__*/React.createElement(StyledInput, {
    className: "c-combo-box-input",
    onBlur: handleBlur,
    onFocus: () => {
      setFocused(!focused);
    },
    onClick: handleOpen,
    ref: handleRef,
    value: loading && loadingText ? loadingText : value,
    onKeyDown: handleOnKeyDown,
    onChange: handleOnChange,
    placeholder: !hasSelected ? placeholder : undefined,
    $mode: triggerMode,
    disabled: disabled,
    $size: size,
    $loading: loading,
    style: {
      display: "flex",
      flex: 1,
      alignSelf: "center",
      width: autoSize === "auto" ? "auto" : "100%"
    }
  })), !disabled && /*#__PURE__*/React.createElement(React.Fragment, null, loading ? /*#__PURE__*/React.createElement(SpinnerLoader, null) : /*#__PURE__*/React.createElement(React.Fragment, null, showXIcon && /*#__PURE__*/React.createElement(_StyledTrigger, {
    onMouseDown: handleMouseDown,
    onClick: handleDeselect,
    "data-testid": "deselect-all"
  }, /*#__PURE__*/React.createElement(StyledComboBoxCloseSmallIcon, null)), showMenu && /*#__PURE__*/React.createElement(StyledComboBoxCollapseExpandSingleIcon, {
    $open: open
  }))))) : /*#__PURE__*/React.createElement(StyledComboBoxInput, {
    className: classNames("c-combo-box-input", inputWrapperClassName),
    onBlur: handleBlur,
    wrapperClick: handleOpen,
    onFocus: () => {
      setFocused(!focused);
      handleOpen();
    },
    onClick: handleOpen,
    mode: triggerMode,
    wrapRef: comboBoxRef,
    ref: handleRef,
    value: loading && loadingText ? loadingText : value,
    onKeyDown: handleOnKeyDown,
    onChange: handleOnChange,
    placeholder: placeholder,
    disabled: disabled,
    size: size,
    invalid: invalid,
    $loading: loading,
    startAdornment: startAdornment,
    endAdornment: !disabled ? /*#__PURE__*/React.createElement(InputAdornment, {
      disablePointerEvents: disabled
    }, loading ? /*#__PURE__*/React.createElement(SpinnerLoader, null) : selected ? /*#__PURE__*/React.createElement(IconButton, {
      onMouseDown: handleMouseDown,
      onClick: handleDeselect,
      variant: "text gray",
      size: "small"
    }, /*#__PURE__*/React.createElement(StyledComboBoxCloseSmallIcon, null)) : null, showMenu && /*#__PURE__*/React.createElement(StyledComboBoxCollapseExpandSingleIcon, {
      $open: open
    })) : null
  }), !disabled ? /*#__PURE__*/React.createElement(ConditionalWrapper, {
    condition: inPortal,
    wrap: children => /*#__PURE__*/React.createElement(Portal, null, children)
  }, /*#__PURE__*/React.createElement(Popper, {
    anchorEl: comboBoxRef.current,
    open: open,
    placement: "bottom",
    style: {
      zIndex: 10,
      width: (_comboBoxRef$current2 = comboBoxRef.current) == null ? void 0 : _comboBoxRef$current2.clientWidth
    },
    ref: wrapperRef,
    strategy: "fixed"
  }, /*#__PURE__*/React.createElement(RemoveScroll, {
    noIsolation: true,
    allowPinchZoom: true
  }, /*#__PURE__*/React.createElement(StyledComboBoxList, {
    className: "c-combo-box--list",
    $width: (_comboBoxRef$current3 = comboBoxRef.current) == null ? void 0 : _comboBoxRef$current3.clientWidth,
    $hide: !showMenu
  }, /*#__PURE__*/React.createElement(Autocomplete, _extends({}, prop, {
    emptyValue: emptyValue,
    noResultText: noResultText,
    inputEl: childNode,
    selected: selected,
    handleChange: handleChange,
    renderOption: handleRenderOption,
    options: options,
    type: type,
    defaultValue: defaultValue,
    handleEmptyAction: emptyAction
  })))))) : null);
};
ComboBox.displayName = "ComboBox";
var _StyledAvatar = _styled(Avatar).withConfig({
  displayName: "ComboBox___StyledAvatar",
  componentId: "sc-uvsz9l-0"
})(["", " ", ""], p => p.$_css, p => p.$_css2);
var _StyledTypography = _styled(Typography).withConfig({
  displayName: "ComboBox___StyledTypography",
  componentId: "sc-uvsz9l-1"
})(["display:flex;flex-shrink:0;align-items:center;"]);
var _StyledStyledInputWrapper = _styled(StyledInputWrapper).withConfig({
  displayName: "ComboBox___StyledStyledInputWrapper",
  componentId: "sc-uvsz9l-2"
})(["display:flex;justify-content:space-between;flex:1;height:", ";overflow-y:", ";"], p => p.$_css3, p => p.$_css4);
var _StyledStyledChipWrapper = _styled(StyledChipWrapper).withConfig({
  displayName: "ComboBox___StyledStyledChipWrapper",
  componentId: "sc-uvsz9l-3"
})(["max-height:", ";"], p => p.$_css5);
var _StyledTrigger = _styled(Trigger).withConfig({
  displayName: "ComboBox___StyledTrigger",
  componentId: "sc-uvsz9l-4"
})(["display:flex;justify-content:center;"]);
//# sourceMappingURL=ComboBox.js.map