import _regeneratorRuntime from "@babel/runtime/regenerator";
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import React from 'react';
import PropTypes from 'prop-types';
import { findDOMNode } from 'react-dom';
import { debounce } from 'lodash';
import { filterKeyCodes } from '../utils/functions';
import { Button } from './Button';
import { TextInput } from './form/TextInput';
import { Icon } from './Icon';
var ELEMENT_SHOW_ALL = 'ELEMENT_SHOW_ALL';
var KEY_CODE_ENTER = 13;
export var Search =
/*#__PURE__*/
function (_React$Component) {
  _inheritsLoose(Search, _React$Component);

  function Search() {
    var _this;

    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }

    _this = _React$Component.call.apply(_React$Component, [this].concat(args)) || this;

    _defineProperty(_assertThisInitialized(_this), "state", {
      focused: false,
      focusedItem: null,
      initial: true,
      results: []
    });

    _defineProperty(_assertThisInitialized(_this), "resultRefs", []);

    _defineProperty(_assertThisInitialized(_this), "inputRef", React.createRef());

    _defineProperty(_assertThisInitialized(_this), "showAllRef", React.createRef());

    _defineProperty(_assertThisInitialized(_this), "blurTimer", void 0);

    _defineProperty(_assertThisInitialized(_this), "handleFocus", function () {
      var value = _this.props.value;
      var initial = _this.state.initial;
      clearTimeout(_this.blurTimer);

      _this.setState({
        focused: true
      });

      if (value && initial) {
        _this.search();
      }
    });

    _defineProperty(_assertThisInitialized(_this), "handleBlur", function () {
      _this.blurTimer = setTimeout(function () {
        _this.setState({
          focused: false,
          focusedItem: null
        });
      }, 0);
    });

    _defineProperty(_assertThisInitialized(_this), "handleKeyboardNavigation", function (e) {
      if (_this.resultRefs.length && (e.key === 'ArrowDown' || e.key === 'ArrowUp')) {
        var focusedItem = _this.state.focusedItem;
        var nextFocusedItem;
        e.stopPropagation();
        e.preventDefault();

        switch (e.key) {
          case 'ArrowDown':
            {
              if (focusedItem === null || focusedItem === ELEMENT_SHOW_ALL) {
                nextFocusedItem = 0;
              } else if (focusedItem === _this.resultRefs.length - 1) {
                nextFocusedItem = ELEMENT_SHOW_ALL;
              } else {
                nextFocusedItem = focusedItem + 1;
              }

              break;
            }

          case 'ArrowUp':
            {
              if (focusedItem === null || focusedItem === 0) {
                nextFocusedItem = ELEMENT_SHOW_ALL;
              } else if (focusedItem === ELEMENT_SHOW_ALL) {
                nextFocusedItem = _this.resultRefs.length - 1;
              } else {
                nextFocusedItem = focusedItem - 1;
              }

              break;
            }
        }

        _this.setState({
          focusedItem: nextFocusedItem
        });

        nextFocusedItem === ELEMENT_SHOW_ALL ? findDOMNode(_this.showAllRef.current).focus() : _this.resultRefs[nextFocusedItem].current.focus();
      }
    });

    _defineProperty(_assertThisInitialized(_this), "search",
    /*#__PURE__*/
    _asyncToGenerator(
    /*#__PURE__*/
    _regeneratorRuntime.mark(function _callee() {
      var _this$props, value, searchProvider;

      return _regeneratorRuntime.wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _this$props = _this.props, value = _this$props.value, searchProvider = _this$props.searchProvider;

              if (value) {
                _context.next = 4;
                break;
              }

              _this.setState({
                results: [],
                initial: true
              });

              return _context.abrupt("return");

            case 4:
              if (!(typeof searchProvider === 'function')) {
                _context.next = 11;
                break;
              }

              _context.t0 = _this;
              _context.next = 8;
              return searchProvider(value);

            case 8:
              _context.t1 = _context.sent;
              _context.t2 = {
                results: _context.t1,
                initial: false,
                focusedItem: null
              };

              _context.t0.setState.call(_context.t0, _context.t2);

            case 11:
            case "end":
              return _context.stop();
          }
        }
      }, _callee);
    })));

    _defineProperty(_assertThisInitialized(_this), "debouncedSearch", debounce(_this.search, _this.props.inputDebounce));

    _defineProperty(_assertThisInitialized(_this), "clear", function () {
      var onChange = _this.props.onChange;

      _this.setState({
        focused: false,
        focusedItem: null
      });

      onChange('');
    });

    _defineProperty(_assertThisInitialized(_this), "handleChange", function (_ref2) {
      var target = _ref2.target;
      var onChange = _this.props.onChange;
      onChange(target.value);
    });

    _defineProperty(_assertThisInitialized(_this), "handleFullSearch", function () {
      var onSearch = _this.props.onSearch;

      _this.setState({
        focused: false
      });

      if (typeof onSearch === 'function') {
        onSearch();
      }
    });

    _defineProperty(_assertThisInitialized(_this), "handleResultAction", function (item) {
      var resultAction = _this.props.resultAction;

      _this.setState({
        focused: false
      });

      if (typeof resultAction === 'function') {
        resultAction(item);
      }
    });

    _defineProperty(_assertThisInitialized(_this), "handleEnter", function (e) {
      if (e.keyCode === KEY_CODE_ENTER && e.currentTarget.tagName === 'INPUT') {
        var $inputContainer = findDOMNode(_this.inputRef.current);

        if ($inputContainer) {
          var $input = $inputContainer.querySelector(':focus');

          if ($input) {
            $input.blur();
          }
        }

        _this.handleFullSearch();
      }
    });

    _defineProperty(_assertThisInitialized(_this), "renderResult", function (item, index) {
      var renderResult = _this.props.renderResult;

      var handler = function handler() {
        return _this.handleResultAction(item);
      };

      _this.resultRefs[index] = React.createRef();
      return React.createElement("li", {
        key: index,
        ref: _this.resultRefs[index],
        role: "button",
        className: "rc-search__result",
        tabIndex: -1,
        onClick: handler,
        onKeyDown: filterKeyCodes(handler),
        "data-test-automation-id": "searchResult" + index
      }, renderResult(item));
    });

    return _this;
  }

  var _proto = Search.prototype;

  _proto.componentDidUpdate = function componentDidUpdate(prevProps) {
    var _this$props2 = this.props,
        value = _this$props2.value,
        inputDebounce = _this$props2.inputDebounce;

    if (value !== prevProps.value) {
      this.debouncedSearch(value);
    }

    if (inputDebounce !== prevProps.inputDebounce) {
      this.debouncedSearch = debounce(this.search, inputDebounce);
    }
  };

  _proto.getResults = function getResults() {
    var maxResults = this.props.maxResults;
    var results = this.state.results;

    if (!maxResults) {
      return results;
    }

    return results.slice(0, maxResults);
  };

  _proto.renderClearButton = function renderClearButton() {
    var textClearLabel = this.props.textClearLabel;
    return React.createElement("button", {
      className: "rc-search__action-button",
      onClick: this.clear,
      "data-test-automation-id": "searchButton",
      "aria-label": textClearLabel
    }, React.createElement(Icon, {
      name: "close"
    }));
  };

  _proto.renderSearchButton = function renderSearchButton() {
    var textSearchLabel = this.props.textSearchLabel;
    return React.createElement("button", {
      disabled: true,
      className: "rc-search__action-button",
      "data-test-automation-id": "searchClear",
      "aria-label": textSearchLabel
    }, React.createElement(Icon, {
      name: "search"
    }));
  };

  _proto.renderSearchInput = function renderSearchInput() {
    var _this$props3 = this.props,
        value = _this$props3.value,
        name = _this$props3.name,
        textSearchPlaceholder = _this$props3.textSearchPlaceholder;
    var focused = this.state.focused;
    var button = !focused || !value ? this.renderSearchButton() : this.renderClearButton();
    return React.createElement("div", {
      className: "rc-search__input-container"
    }, React.createElement(TextInput, {
      testAutomationId: "searchInput",
      ref: this.inputRef,
      autoComplete: "off",
      value: value,
      name: name,
      placeholder: textSearchPlaceholder,
      onChange: this.handleChange,
      onKeyDown: this.handleEnter,
      "aria-label": textSearchPlaceholder
    }), button);
  };

  _proto.renderResults = function renderResults() {
    var _this$props4 = this.props,
        value = _this$props4.value,
        textShowAllResults = _this$props4.textShowAllResults,
        textNoResults = _this$props4.textNoResults;
    var _this$state = this.state,
        focused = _this$state.focused,
        results = _this$state.results,
        initial = _this$state.initial;
    this.resultRefs = [];

    if (!focused || !value || !results.length && initial) {
      return null;
    }

    var content = !results.length ? React.createElement("div", {
      className: "rc-search__no-result",
      "data-test-automation-id": "searchNoResults"
    }, textNoResults) : React.createElement(React.Fragment, null, React.createElement("ul", {
      className: "rc-search__results-list",
      "data-test-automation-id": "searchResultsList"
    }, this.getResults().map(this.renderResult)), React.createElement(Button, {
      ref: this.showAllRef,
      className: "rc-search__results-footer",
      onClick: this.handleFullSearch,
      testAutomationId: "searchShowAll"
    }, textShowAllResults, " \"", value, "\""));
    return React.createElement("div", {
      className: "rc-search__results",
      "data-test-automation-id": "searchResults"
    }, content);
  };

  _proto.render = function render() {
    var testAutomationId = this.props.testAutomationId;
    return React.createElement("div", {
      className: "rc-search",
      "data-test-automation-id": testAutomationId,
      onFocus: this.handleFocus,
      onBlur: this.handleBlur,
      onKeyDown: this.handleKeyboardNavigation
    }, this.renderSearchInput(), this.renderResults());
  };

  return Search;
}(React.Component);

_defineProperty(Search, "propTypes", {
  value: PropTypes.string,
  name: PropTypes.string,
  inputDebounce: PropTypes.number,
  renderResult: PropTypes.func.isRequired,
  searchProvider: PropTypes.func.isRequired,
  onChange: PropTypes.func.isRequired,
  onSearch: PropTypes.func.isRequired,
  resultAction: PropTypes.func.isRequired,
  maxResults: PropTypes.number,
  testAutomationId: PropTypes.string,
  textSearchPlaceholder: PropTypes.string,
  textNoResults: PropTypes.string,
  textShowAllResults: PropTypes.string,
  textSearchLabel: PropTypes.string,
  textClearLabel: PropTypes.string
});

_defineProperty(Search, "defaultProps", {
  value: null,
  name: null,
  inputDebounce: 500,
  maxResults: 3,
  textSearchPlaceholder: 'Search',
  textShowAllResults: 'Show all results for:',
  textNoResults: 'No result found. Please try different keyword for your search.',
  textSearchLabel: 'Search',
  textClearLabel: 'Clear',
  testAutomationId: 'search'
});