"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

exports.__esModule = true;
exports.Search = void 0;

var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));

var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));

var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));

var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose"));

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));

var _react = _interopRequireDefault(require("react"));

var _propTypes = _interopRequireDefault(require("prop-types"));

var _reactDom = require("react-dom");

var _lodash = require("lodash");

var _functions = require("../utils/functions");

var _Button = require("./Button");

var _TextInput = require("./form/TextInput");

var _Icon = require("./Icon");

var ELEMENT_SHOW_ALL = 'ELEMENT_SHOW_ALL';
var KEY_CODE_ENTER = 13;

var Search =
/*#__PURE__*/
function (_React$Component) {
  (0, _inheritsLoose2.default)(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;
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "state", {
      focused: false,
      focusedItem: null,
      initial: true,
      results: []
    });
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "resultRefs", []);
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "inputRef", _react.default.createRef());
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "showAllRef", _react.default.createRef());
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "blurTimer", void 0);
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_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();
      }
    });
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "handleBlur", function () {
      _this.blurTimer = setTimeout(function () {
        _this.setState({
          focused: false,
          focusedItem: null
        });
      }, 0);
    });
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_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 ? (0, _reactDom.findDOMNode)(_this.showAllRef.current).focus() : _this.resultRefs[nextFocusedItem].current.focus();
      }
    });
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "search",
    /*#__PURE__*/
    (0, _asyncToGenerator2.default)(
    /*#__PURE__*/
    _regenerator.default.mark(function _callee() {
      var _this$props, value, searchProvider;

      return _regenerator.default.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);
    })));
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "debouncedSearch", (0, _lodash.debounce)(_this.search, _this.props.inputDebounce));
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "clear", function () {
      var onChange = _this.props.onChange;

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

      onChange('');
    });
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "handleChange", function (_ref2) {
      var target = _ref2.target;
      var onChange = _this.props.onChange;
      onChange(target.value);
    });
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "handleFullSearch", function () {
      var onSearch = _this.props.onSearch;

      _this.setState({
        focused: false
      });

      if (typeof onSearch === 'function') {
        onSearch();
      }
    });
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "handleResultAction", function (item) {
      var resultAction = _this.props.resultAction;

      _this.setState({
        focused: false
      });

      if (typeof resultAction === 'function') {
        resultAction(item);
      }
    });
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "handleEnter", function (e) {
      if (e.keyCode === KEY_CODE_ENTER && e.currentTarget.tagName === 'INPUT') {
        var $inputContainer = (0, _reactDom.findDOMNode)(_this.inputRef.current);

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

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

        _this.handleFullSearch();
      }
    });
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "renderResult", function (item, index) {
      var renderResult = _this.props.renderResult;

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

      _this.resultRefs[index] = _react.default.createRef();
      return _react.default.createElement("li", {
        key: index,
        ref: _this.resultRefs[index],
        role: "button",
        className: "rc-search__result",
        tabIndex: -1,
        onClick: handler,
        onKeyDown: (0, _functions.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 = (0, _lodash.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.default.createElement("button", {
      className: "rc-search__action-button",
      onClick: this.clear,
      "data-test-automation-id": "searchButton",
      "aria-label": textClearLabel
    }, _react.default.createElement(_Icon.Icon, {
      name: "close"
    }));
  };

  _proto.renderSearchButton = function renderSearchButton() {
    var textSearchLabel = this.props.textSearchLabel;
    return _react.default.createElement("button", {
      disabled: true,
      className: "rc-search__action-button",
      "data-test-automation-id": "searchClear",
      "aria-label": textSearchLabel
    }, _react.default.createElement(_Icon.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.default.createElement("div", {
      className: "rc-search__input-container"
    }, _react.default.createElement(_TextInput.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.default.createElement("div", {
      className: "rc-search__no-result",
      "data-test-automation-id": "searchNoResults"
    }, textNoResults) : _react.default.createElement(_react.default.Fragment, null, _react.default.createElement("ul", {
      className: "rc-search__results-list",
      "data-test-automation-id": "searchResultsList"
    }, this.getResults().map(this.renderResult)), _react.default.createElement(_Button.Button, {
      ref: this.showAllRef,
      className: "rc-search__results-footer",
      onClick: this.handleFullSearch,
      testAutomationId: "searchShowAll"
    }, textShowAllResults, " \"", value, "\""));
    return _react.default.createElement("div", {
      className: "rc-search__results",
      "data-test-automation-id": "searchResults"
    }, content);
  };

  _proto.render = function render() {
    var testAutomationId = this.props.testAutomationId;
    return _react.default.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.default.Component);

exports.Search = Search;
(0, _defineProperty2.default)(Search, "propTypes", {
  value: _propTypes.default.string,
  name: _propTypes.default.string,
  inputDebounce: _propTypes.default.number,
  renderResult: _propTypes.default.func.isRequired,
  searchProvider: _propTypes.default.func.isRequired,
  onChange: _propTypes.default.func.isRequired,
  onSearch: _propTypes.default.func.isRequired,
  resultAction: _propTypes.default.func.isRequired,
  maxResults: _propTypes.default.number,
  testAutomationId: _propTypes.default.string,
  textSearchPlaceholder: _propTypes.default.string,
  textNoResults: _propTypes.default.string,
  textShowAllResults: _propTypes.default.string,
  textSearchLabel: _propTypes.default.string,
  textClearLabel: _propTypes.default.string
});
(0, _defineProperty2.default)(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'
});