"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.default = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _react = require("react");
var _debounce2 = _interopRequireDefault(require("lodash/debounce"));
var _useIsMounted = _interopRequireDefault(require("../useIsMounted"));
var _useDebouncedCallback = _interopRequireDefault(require("../useDebouncedCallback/useDebouncedCallback"));
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
var initialFetchState = {
  loading: false,
  predictions: []
};

/** A hook for fetching place predictions based on input value */
var usePlacesAutocomplete = _ref => {
  var {
    /** client: connects and sends requests to location service (Atlas / Google)
     * contains: {
     *  fetchPredictions: A function that fetches predictions from service given input value
     *  ready: is client ready to receive requests
     * } */
    client,
    /** fetch predictions debounce in milliseconds (default: 200) */
    debounceMs = 200,
    /** (callback: Function, debounceMs: number) => Function
     * allow passing a custom debounce function (default: lodash debounce) */
    debounceFn = _debounce2.default,
    /** method to be called when a fetch error occurs */
    onError
  } = _ref;
  var [{
    /** whether fetch request is ongoing */
    loading,
    /** array of prediction results */
    predictions
  }, setFetchState] = (0, _react.useState)(initialFetchState);
  var predictionsRequestId = (0, _react.useRef)(0); // id of latest request to avoid race conditions
  var isMounted = (0, _useIsMounted.default)(); // checks whether component is still mounted

  var clearPredictions = (0, _react.useCallback)(() => {
    // Increase request id counter
    predictionsRequestId.current++;
    setFetchState(initialFetchState);
  }, []);
  var updatePredictions = (0, _useDebouncedCallback.default)(/*#__PURE__*/function () {
    var _ref2 = (0, _asyncToGenerator2.default)(function* (value, requestOptions) {
      var {
        ready,
        fetchPredictions
      } = client;
      if (!ready || !isMounted()) {
        return;
      }
      if (!value) {
        clearPredictions();
        return;
      }

      // Increase request id counter
      var requestId = ++predictionsRequestId.current;
      setFetchState(state => _objectSpread(_objectSpread({}, state), {}, {
        loading: true
      }));
      var newPredictions;
      try {
        newPredictions = yield fetchPredictions(value, requestOptions);
      } catch (error) {
        // failed to fetch predictions
        if (onError) {
          onError(error);
        } else {
          // eslint-disable-next-line no-console
          console.log(error);
        }
      } finally {
        // check if no new fetch request has been initiated
        var isMostRecentRequest = requestId === predictionsRequestId.current;
        if (isMounted() && isMostRecentRequest) {
          setFetchState(state => ({
            loading: false,
            // set new predictions if fetched properly, else keep current predictions
            predictions: newPredictions || state.predictions
          }));
        }
      }
    });
    return function (_x, _x2) {
      return _ref2.apply(this, arguments);
    };
  }(), [client, onError], debounceMs, debounceFn);
  return {
    /** array of prediction results */
    predictions,
    /** whether fetch request is ongoing */
    loading,
    /** (value: string, requestOptions?: RequestOptions) => void
     * fetches predictions for given value from client (debounced)
     * and sets results to prediction state.
     *
     * Can also receive requestOptions,
     * which are client specific options to pass to the request */
    updatePredictions,
    /** function that clears predictions array and sets loading state to false */
    clearPredictions
  };
};
var _default = exports.default = usePlacesAutocomplete;
//# sourceMappingURL=usePlacesAutocomplete.js.map