import _defineProperty from "@babel/runtime/helpers/defineProperty";
// Copyright 1999-2023. Plesk International GmbH. All rights reserved.

import classNames from 'classnames';
import { Children, cloneElement, Component, useContext } from 'react';
import { CLS_PREFIX } from '../../constants';
import { isRtl } from '../../utils';
import Badge from '../Badge';
import Button from '../Button';
import DistractionFreeModeContext from '../DistractionFreeModeContext';
import Input from '../Input';
import Menu, { MenuItem, MenuSelectableItem } from '../Menu';
import ResponsiveContext from '../ResponsiveContext';
import { safeInvoke } from '../utils';
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
/**
 * `SearchBar` component is used for providing type-as-you-go search.
 * @since 0.0.58
 */
class SearchBar extends Component {
  constructor() {
    super(...arguments);
    _defineProperty(this, "state", {
      focused: false,
      overMenu: false,
      value: `${this.props.inputProps?.value || ''}`,
      highlightedValue: null
    });
    _defineProperty(this, "isFocusScheduled", false);
    _defineProperty(this, "search", void 0);
    _defineProperty(this, "keyboardNavigation", key => {
      const {
        onItemSelect,
        results
      } = this.props;
      const highlightedValue = this.getHighlightedValue();
      if (!results || !onItemSelect) {
        return;
      }
      const res = this.getResults();
      const currentIndex = res.indexOf(highlightedValue);
      let nextIndex;
      if (key === 'ArrowUp') {
        nextIndex = Math.max(currentIndex - 1, 0);
      } else {
        nextIndex = Math.min(currentIndex + 1, res.length - 1);
      }
      this.setState({
        highlightedValue: currentIndex === -1 ? null : res[nextIndex]
      });
    });
    _defineProperty(this, "handleFocus", () => {
      this.setState({
        focused: true
      });
      this.search && this.search.focus();
    });
    _defineProperty(this, "handleBlur", () => {
      this.setState({
        focused: false
      });
      this.search && this.search.blur();
    });
    _defineProperty(this, "handleMenuMouseOver", () => {
      this.setState({
        overMenu: true
      });
    });
    _defineProperty(this, "handleMenuMouseOut", () => {
      this.setState({
        overMenu: false
      });
    });
    _defineProperty(this, "handleKeyDown", e => {
      const {
        onTyping
      } = this.props;
      const {
        value
      } = e.currentTarget;
      if (['Enter', 'Escape', 'ArrowUp', 'ArrowDown'].indexOf(e.key) !== -1) {
        this.checkKeys(e.key);
        return;
      }
      this.setState({
        value
      });
      if (onTyping) {
        onTyping(value, () => this.clearInput());
      }
    });
    _defineProperty(this, "handleSearch", () => {
      const {
        onSearch,
        onTyping
      } = this.props;
      const {
        value
      } = this.state;
      if (onSearch) {
        onSearch(value, () => this.clearInput());
      } else if (onTyping) {
        onTyping(value, () => this.clearInput());
      }
    });
    _defineProperty(this, "handleReset", () => {
      this.clearInput();
      this.handleFocus();
    });
    _defineProperty(this, "handleSelect", value => () => {
      const {
        onItemSelect
      } = this.props;
      this.setState({
        highlightedValue: null
      });
      this.handleBlur();
      if (onItemSelect) {
        onItemSelect(value, () => this.clearInput());
      } else {
        this.clearInput();
      }
    });
    _defineProperty(this, "handleExpand", () => {
      const {
        onExpand,
        distractionFreeMode
      } = this.props;
      this.isFocusScheduled = true;
      safeInvoke(onExpand);
      if (distractionFreeMode) {
        distractionFreeMode.toggle();
      }
    });
    _defineProperty(this, "handleCollapse", () => {
      const {
        onCollapse,
        distractionFreeMode
      } = this.props;
      safeInvoke(onCollapse);
      if (distractionFreeMode) {
        distractionFreeMode.toggle();
      }
    });
  }
  static getDerivedStateFromProps(props, state) {
    const {
      inputProps: {
        value: inputPropsValue
      } = {}
    } = props;
    const {
      prevInputProps: {
        value: prevInputPropsValue
      } = {}
    } = state;
    const nextState = {};
    if (inputPropsValue !== prevInputPropsValue) {
      nextState.value = inputPropsValue ?? '';
    }
    nextState.prevInputProps = props.inputProps;
    return nextState;
  }
  componentDidUpdate() {
    if (this.isFocusScheduled) {
      this.handleFocus();
      this.isFocusScheduled = false;
    }
  }
  isResponsive() {
    return this.props.responsive;
  }
  getResults(innerResults) {
    const {
      results
    } = this.props;
    if (!results) {
      return [];
    }
    if ('type' in results && results.type === Menu || innerResults) {
      let res = [];
      const children = innerResults || results.props.children;
      if (!Array.isArray(children)) {
        return res;
      }
      for (let i = 0; i < children.length; i++) {
        const child = children[i];
        if (!child) {
          continue;
        }
        if (Children.count(child) > 1) {
          res = res.concat(this.getResults(child));
        } else if ((child.type === MenuItem || child.type === MenuSelectableItem) && child.key) {
          res.push(child.key.toString());
        }
      }
      return res;
    }
    return results.map(_ref => {
      let {
        value
      } = _ref;
      return value;
    });
  }
  getHighlightedValue() {
    return (this.state.highlightedValue || this.getResults()[0]) ?? null;
  }
  searchAction() {
    const {
      onItemSelect,
      results
    } = this.props;
    const highlightedValue = this.getHighlightedValue();
    if (onItemSelect && results) {
      const res = this.getResults();
      const currentIndex = res.indexOf(highlightedValue);
      if (currentIndex === -1) {
        this.handleSearch();
      } else {
        this.handleSelect(highlightedValue)();
      }
    } else {
      this.handleSearch();
    }
  }
  checkKeys(key) {
    if (key === 'Enter') {
      this.searchAction();
    } else if (key === 'Escape') {
      if (this.state.value) {
        this.handleReset();
      } else {
        this.handleBlur();
        this.handleMenuMouseOut();
      }
    } else if (key === 'ArrowUp' || key === 'ArrowDown') {
      this.keyboardNavigation(key);
    }
  }
  clearInput() {
    this.setState({
      value: ''
    }, this.handleSearch);
  }
  elementsIndexToKeyMapping(elements) {
    let result = [];
    if (!Array.isArray(elements)) {
      return result;
    }
    for (let i = 0; i < elements.length; i++) {
      const element = elements[i];
      if (!element) {
        continue;
      }
      if (Array.isArray(element)) {
        result = result.concat(this.elementsIndexToKeyMapping(element));
      } else {
        result.push(element.key);
      }
    }
    return result;
  }
  renderResults(results) {
    const {
      baseClassName
    } = this.props;
    const {
      focused,
      overMenu
    } = this.state;
    const highlightedValue = this.getHighlightedValue();
    return /*#__PURE__*/_jsx(Menu, {
      className: classNames(`${baseClassName}__results`, {
        [`${baseClassName}__results--hidden`]: !focused && !overMenu
      }),
      onMouseOver: this.handleMenuMouseOver,
      onMouseOut: this.handleMenuMouseOut,
      children: results.map(item => /*#__PURE__*/_jsx(MenuItem, {
        active: item.value === highlightedValue,
        onClick: this.handleSelect(item.value),
        children: item.title
      }, item.value))
    });
  }
  renderResultsMenu(results) {
    const {
      baseClassName,
      onItemSelect
    } = this.props;
    const {
      focused,
      overMenu
    } = this.state;
    const highlightedValue = this.getHighlightedValue();
    return /*#__PURE__*/cloneElement(results, {
      className: classNames(`${baseClassName}__results`, {
        [`${baseClassName}__results--hidden`]: !focused && !overMenu
      }, results.props.className),
      onMouseOver: this.handleMenuMouseOver,
      onMouseOut: this.handleMenuMouseOut,
      onItemClick: (_item, index) => {
        const indexMap = this.elementsIndexToKeyMapping(results.props.children);
        this.handleSelect(indexMap[index])();
      },
      children: Children.map(results.props.children, child => {
        if (onItemSelect && child && typeof child === 'object' && 'type' in child && (child.type === MenuItem || child.type === MenuSelectableItem)) {
          return /*#__PURE__*/cloneElement(child, {
            active: child.key === highlightedValue
          });
        }
        return child;
      })
    });
  }
  render() {
    const {
      baseClassName,
      className,
      maxWidth,
      minWidth,
      loading,
      responsive,
      onSearch,
      onTyping,
      onItemSelect,
      collapsable,
      onCollapse,
      onExpand,
      results,
      inputProps,
      distractionFreeMode,
      ...props
    } = this.props;
    const {
      focused,
      value
    } = this.state;
    const isCollapsed = this.isResponsive();
    const distractionFreeModeEnabled = Boolean(distractionFreeMode && distractionFreeMode.enabled);
    return /*#__PURE__*/_jsx("div", {
      className: classNames(baseClassName, {
        [`${baseClassName}--focused`]: focused
      }, className),
      style: isCollapsed || distractionFreeModeEnabled ? undefined : {
        maxWidth,
        minWidth
      },
      ...props,
      children: isCollapsed && (collapsable || !distractionFreeModeEnabled) ? /*#__PURE__*/_jsx(Badge, {
        intent: "info",
        hidden: !value,
        children: /*#__PURE__*/_jsx(Button, {
          icon: "search",
          onClick: this.handleExpand
        })
      }) : /*#__PURE__*/_jsxs("div", {
        className: `${baseClassName}__group`,
        children: [/*#__PURE__*/_jsx(Input, {
          innerRef: ref => this.search = ref,
          className: `${baseClassName}__input`,
          size: "fill",
          onChange: this.handleKeyDown,
          onFocus: this.handleFocus,
          onBlur: this.handleBlur,
          onKeyDown: this.handleKeyDown,
          ...inputProps,
          value: value,
          prefix: (collapsable && !isCollapsed || distractionFreeModeEnabled) && /*#__PURE__*/_jsx(Button, {
            icon: {
              name: 'chevron-right',
              flipHorizontal: isRtl()
            },
            ghost: true,
            onClick: this.handleCollapse
          }),
          suffix: /*#__PURE__*/_jsxs(_Fragment, {
            children: [value && /*#__PURE__*/_jsx(Button, {
              icon: "remove",
              onClick: this.handleReset,
              ghost: true
            }), /*#__PURE__*/_jsx(Button, {
              icon: "search",
              onClick: this.handleSearch,
              state: loading ? 'loading' : undefined,
              ghost: true
            })]
          })
        }), Array.isArray(results) && this.renderResults(results), results && !Array.isArray(results) && results.type === Menu && this.renderResultsMenu(results)]
      })
    });
  }
}
_defineProperty(SearchBar, "defaultProps", {
  baseClassName: `${CLS_PREFIX}search-bar`,
  maxWidth: 500,
  minWidth: 270,
  inputProps: {}
});
const SearchBarWrapper = props => {
  const distractionFreeMode = useContext(DistractionFreeModeContext);
  let responsive = useContext(ResponsiveContext);
  responsive = props.responsive === undefined ? responsive || false : Boolean(props.responsive);
  return /*#__PURE__*/_jsx(SearchBar, {
    ...props,
    responsive: responsive,
    distractionFreeMode: distractionFreeMode
  });
};
SearchBarWrapper.displayName = 'SearchBar';
export default SearchBarWrapper;