"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.Finder = void 0;
var _dataSources = require("@mirai/data-sources");
var _locale = require("@mirai/locale");
var _ui = require("@mirai/ui");
var _propTypes = _interopRequireDefault(require("prop-types"));
var _react = _interopRequireWildcard(require("react"));
var _components = require("./components");
var _Finder = require("./Finder.compact");
var _Finder2 = require("./Finder.constants");
var _Finder3 = require("./Finder.l10n");
var style = _interopRequireWildcard(require("./Finder.module.css"));
var _helpers = require("./helpers");
var _getAvailableWidth = require("./helpers/getAvailableWidth");
var _helpers2 = require("../../helpers");
var _prepareRoom = require("../../helpers/prepareRoom");
var _shared__ = require("../__shared__");
var _Occupation = require("../__shared__/Occupation/Occupation.constants");
var _helpers3 = require("../helpers");
const _excluded = ["compacted", "icon", "layout", "storage", "text", "onChange", "onSubmit"],
  _excluded2 = ["components", "currency", "finder", "forwarder", "locale", "promo", "skeleton", "type"],
  _excluded3 = ["separatorColor"]; // ! TODO: Why we don't publish prepareRoom in ../../helpers
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
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) { _defineProperty(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; }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
const {
  CHAIN,
  HOTEL
} = _Finder2.TYPE;
const Finder = _ref => {
  var _dataSource$places, _dataSource$places2, _dataSource$places2$o, _dataSource$places3, _dataSource$places4, _dataSource$places5;
  let {
      compacted = false,
      icon = false,
      layout,
      storage = true,
      text,
      onChange = () => {},
      onSubmit
    } = _ref,
    others = _objectWithoutProperties(_ref, _excluded);
  const {
    isMobile,
    width: deviceWidth
  } = (0, _ui.useDevice)();
  const {
    dateFormat,
    translate
  } = (0, _locale.useLocale)();
  const ref = (0, _react.useRef)(null);
  const placesRef = (0, _react.useRef)(null);
  const _useStore = (0, _dataSources.useStore)(),
    {
      set,
      value: {
        components = {},
        currency: propCurrency,
        finder: storeFinder,
        forwarder,
        locale,
        promo = {},
        skeleton = false,
        type = HOTEL
      }
    } = _useStore,
    store = _objectWithoutProperties(_useStore.value, _excluded2);
  const [currency, setCurrency] = (0, _react.useState)();
  const [error, setError] = (0, _react.useState)({});
  const [focus, setFocus] = (0, _react.useState)();
  const [unavailability, setUnavailability] = (0, _react.useState)();
  const [value, setValue] = (0, _react.useState)((0, _helpers.parseValue)(storeFinder));
  const [visited, setVisited] = (0, _react.useState)({});
  const [warning, setWarning] = (0, _react.useState)();
  const [width, setWidth] = (0, _react.useState)();
  (0, _react.useEffect)(() => {
    if (skeleton) return;
    if (!(storeFinder !== null && storeFinder !== void 0 && storeFinder.occupation)) set({
      finder: _objectSpread(_objectSpread({}, storeFinder), {}, {
        occupation: [(0, _prepareRoom.prepareRoom)(_Occupation.DATASOURCE)]
      })
    });
    if (is.debug && !(storeFinder !== null && storeFinder !== void 0 && storeFinder.occupation)) {
      // eslint-disable-next-line no-console
      console.log({
        finder: _objectSpread(_objectSpread({}, storeFinder), {}, {
          occupation: [(0, _prepareRoom.prepareRoom)(_Occupation.DATASOURCE)]
        })
      });
    }
    window.addEventListener('pageshow', handlePageShow);
    !isMobile && document.addEventListener('click', handleClickOutside, true);
    return () => {
      window.removeEventListener('pageshow', handlePageShow);
      !isMobile && document.removeEventListener('click', handleClickOutside, true);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);
  (0, _react.useEffect)(() => {
    const {
      current: el
    } = ref || {};
    if (!is.column || !el) return;
    const observer = new IntersectionObserver(function () {
      let [{
        isIntersecting
      } = {}] = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
      return isIntersecting && setWidth((0, _getAvailableWidth.getAvailableWidth)(el));
    }, {
      threshold: 0.1
    });
    if (el) observer.observe(el);
    return () => {
      if (el) observer.unobserve(el);
    };

    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [deviceWidth]);
  (0, _react.useEffect)(() => {
    unavailability && setUnavailability({
      disabledDates: []
    });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [value === null || value === void 0 ? void 0 : value.occupation, value === null || value === void 0 ? void 0 : value.place]);
  (0, _react.useEffect)(() => {
    var _fetchUrlParams;
    const {
      place: {
        id: [hotelId] = [],
        isHotel
      } = {}
    } = value || {};
    const nextPromocode = !is.rates && (promo.variants && promo.variants[hotelId] || promo.code);
    if (nextPromocode) {
      const next = _objectSpread(_objectSpread({}, value), {}, {
        promocode: nextPromocode
      });
      setValue(next);
      publishChange(next);
    }
    if (isHotel && !((_fetchUrlParams = (0, _helpers2.fetchUrlParams)(window.location.search)) !== null && _fetchUrlParams !== void 0 && _fetchUrlParams.currency)) {
      (async () => setCurrency(await (0, _helpers2.fetchCurrency)(hotelId)))();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [value === null || value === void 0 ? void 0 : value.place]);
  (0, _react.useEffect)(() => {
    const handleFinder = function () {
      let {
        calendar,
        finder,
        focus
      } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      if (finder) return handleSubmit({
        nextValue: finder
      });
      setUnavailability(calendar);
      if (focus) setFocus(focus);
    };
    _dataSources.Event.subscribe(_helpers3.EVENT.FINDER, handleFinder);
    return () => _dataSources.Event.unsubscribe(_helpers3.EVENT.FINDER, handleFinder);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [locale, propCurrency]);

  // ! TODO: Why this one? Is not responsibility of <Finder> change the currency when prop changes.
  (0, _react.useEffect)(() => {
    setCurrency(id ? propCurrency : undefined);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [propCurrency]);
  (0, _react.useEffect)(() => {
    const next = (0, _helpers.parseValue)(_objectSpread(_objectSpread({}, value), storeFinder));
    if (JSON.stringify(value) !== JSON.stringify(next)) {
      setValue(next);
      publishChange(next);
    }
  },
  // eslint-disable-next-line react-hooks/exhaustive-deps
  [storeFinder]);
  (0, _react.useEffect)(() => {
    focus && setVisited(_objectSpread(_objectSpread({}, visited), {}, {
      ["".concat(focus)]: true
    }));
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [focus]);
  const handleChange = (field, fieldValue) => {
    const next = _objectSpread(_objectSpread({}, value), {}, {
      [field]: fieldValue
    });
    setValue(next);
    onChange(next, field, fieldValue);
    publishChange(next);
  };
  const handleClickOutside = function () {
    var _ref$current;
    let {
      target
    } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
    return !((_ref$current = ref.current) !== null && _ref$current !== void 0 && _ref$current.contains(target)) && setFocus(undefined);
  };
  const handlePageShow = function () {
    let {
      persisted
    } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
    if (!persisted) return;
    setFocus();
    setVisited();
    const next = (0, _helpers.parseValue)(storeFinder);
    setValue(next);
    publishChange(next);
  };
  const handlePlaceChange = place => {
    setWarning(false);
    handleChange(_Finder2.VIEW.PLACE, place);
    !is.rates && assistant();
  };
  const handleSubmit = function () {
    var _value$calendar, _nextValue;
    let {
      nextValue = value
    } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
    if (dataSource.places && value.place === undefined) return setFocus(_Finder2.VIEW.PLACE);
    if (((_value$calendar = value.calendar) === null || _value$calendar === void 0 ? void 0 : _value$calendar.length) !== 2) return setFocus(_Finder2.VIEW.CALENDAR);
    const [firstError] = Object.keys(error).filter(key => !!error[key]);
    if (firstError) return setFocus(firstError);
    setWarning(false);
    setFocus(undefined);
    if (!((_nextValue = nextValue) !== null && _nextValue !== void 0 && _nextValue.occupation)) {
      nextValue = _objectSpread(_objectSpread({}, nextValue), {}, {
        occupation: [(0, _prepareRoom.prepareRoom)(_Occupation.DATASOURCE)]
      });
    }
    set({
      finder: nextValue
    });
    const forwarderUrl = (0, _helpers.getForwarderUrl)(_objectSpread(_objectSpread({}, nextValue), {}, {
      currency,
      forwarder,
      locale,
      store,
      type
    }));
    storage && (0, _helpers.setStorage)(nextValue, store === null || store === void 0 ? void 0 : store.id);
    if (onSubmit) onSubmit(_objectSpread(_objectSpread({}, nextValue), {}, {
      forwarderUrl
    }));else window.location.href = forwarderUrl;
  };
  const assistant = () => {
    const {
      calendar = []
    } = value;
    if (focus === _Finder2.VIEW.PLACE && !visited.calendar && calendar.length !== 2) setFocus(_Finder2.VIEW.CALENDAR);else if (!compacted || [_Finder2.VIEW.CALENDAR, _Finder2.VIEW.PLACE].includes(focus)) setFocus(undefined);
  };
  const publishChange = next => Object.keys(next || []).forEach(field => {
    if (JSON.stringify(value[field]) !== JSON.stringify(next[field])) {
      _dataSources.Event.publish(_helpers3.EVENT.FINDER_FIELD_CHANGE, {
        field,
        previousValue: value[field],
        value: next[field]
      });
    }
  });
  const {
    calendar = [],
    occupation,
    place = {},
    promocode
  } = value;
  const {
    id: ids = [],
    isHotel
  } = place;
  const dataSource = (0, _helpers.getDataSource)(_objectSpread({
    type
  }, store));
  const {
    hotel: {
      id: idHotel
    } = {}
  } = store;
  const id = type !== HOTEL ? isHotel && ids.length === 1 ? ids[0] : undefined : idHotel;
  const _Theme$get = _ui.Theme.get('--mirai-finder-field-'),
    {
      separatorColor = ''
    } = _Theme$get,
    fieldVariant = _objectWithoutProperties(_Theme$get, _excluded3);
  const is = {
    inline: separatorColor !== 'transparent',
    column: layout === 'column',
    expand: !isMobile && layout === 'expand',
    compacted: layout !== 'column' && (isMobile || compacted && !focus),
    debug: (store === null || store === void 0 ? void 0 : store.id) === '500138',
    rates: components.rates !== undefined
  };
  const fieldProps = _objectSpread(_objectSpread({
    compacted: is.compacted,
    hasPlaces: !!dataSource.places,
    inline: is.inline
  }, !is.compacted ? (0, _helpers.getFieldPosition)(ref, placesRef) : undefined), {}, {
    text: is.rates ? translate(_Finder3.L10N.ACTION_SEARCH) : translate(_Finder3.L10N.ACTION_APPLY),
    variant: Object.keys(fieldVariant).length ? fieldVariant : undefined,
    className: style.field,
    style: is.column && width ? {
      maxWidth: width,
      width
    } : undefined
  });

  // eslint-disable-next-line no-console
  is.debug && console.log({
    place,
    calendar,
    occupation
  });
  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, is.compacted && /*#__PURE__*/_react.default.createElement(_Finder.Compact, _extends({
    dataSource,
    skeleton,
    value,
    onExpand: setFocus,
    onSubmit: !is.rates || is.rates && !isMobile ? handleSubmit : undefined
  }, others)), /*#__PURE__*/_react.default.createElement(_ui.View, {
    ref: ref,
    role: "finder",
    row: !is.column,
    tag: "finder",
    testId: others.testId,
    className: !is.compacted ? (0, _ui.styles)(style.finder, is.column && style.column, is.expand && style.expand, others.className) : undefined
  }, (dataSource.places || skeleton && type === CHAIN) && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_shared__.Field, _extends({}, _Finder2.FIELD.PLACE, {
    caption: (0, _helpers.getPlaceCaption)(place.value, (_dataSource$places = dataSource.places) === null || _dataSource$places === void 0 ? void 0 : _dataSource$places.options),
    label: translate(_Finder3.L10N.LABEL_WHERE),
    expanded: (dataSource === null || dataSource === void 0 ? void 0 : (_dataSource$places2 = dataSource.places) === null || _dataSource$places2 === void 0 ? void 0 : (_dataSource$places2$o = _dataSource$places2.options) === null || _dataSource$places2$o === void 0 ? void 0 : _dataSource$places2$o.length) >= _Finder2.PLACES_LENGTH_LIMIT,
    markdown: false,
    placeholder: (dataSource === null || dataSource === void 0 ? void 0 : (_dataSource$places3 = dataSource.places) === null || _dataSource$places3 === void 0 ? void 0 : _dataSource$places3.placeholder) || translate(_Finder3.L10N.LABEL_WHERE_PLACEHOLDER),
    visible: focus === _Finder2.VIEW.PLACE,
    onPress: () => setFocus(focus !== _Finder2.VIEW.PLACE ? _Finder2.VIEW.PLACE : undefined)
  }, fieldProps), /*#__PURE__*/_react.default.createElement(_components.Places, {
    autoColumn: focus === _Finder2.VIEW.PLACE,
    dataSource: dataSource === null || dataSource === void 0 ? void 0 : (_dataSource$places4 = dataSource.places) === null || _dataSource$places4 === void 0 ? void 0 : _dataSource$places4.options,
    text: compacted ? text : undefined,
    ref: placesRef,
    value: place.value,
    onChange: handlePlaceChange,
    onSubmit: is.rates ? handleSubmit : undefined,
    testId: others.testId ? "".concat(others.testId, "-places") : undefined
  })), is.inline && /*#__PURE__*/_react.default.createElement(_ui.View, {
    className: style.separator
  })), /*#__PURE__*/_react.default.createElement(_shared__.Field, _extends({}, _Finder2.FIELD.CALENDAR, {
    caption: calendar.length ? (0, _helpers3.getCalendarCaption)(calendar, translate, dateFormat) : undefined,
    centered: type !== HOTEL && !is.column,
    label: translate(_Finder3.L10N.LABEL_WHEN),
    placeholder: (0, _helpers3.getCalendarCaption)(undefined, translate, dateFormat),
    visible: focus === _Finder2.VIEW.CALENDAR,
    onPress: () => setFocus(focus !== _Finder2.VIEW.CALENDAR ? _Finder2.VIEW.CALENDAR : undefined),
    testId: others.testId ? "".concat(others.testId, "-calendar-field") : undefined
  }, fieldProps), /*#__PURE__*/_react.default.createElement(_components.Calendar, _extends({}, (0, _helpers.parseCalendarProps)(dataSource.calendar, id, occupation, type, unavailability, dataSource.variants), {
    id: id,
    currency: id ? currency : undefined,
    locale: locale,
    rangeMinDays: 1,
    text: compacted ? text : undefined,
    top: fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.top,
    skeleton: skeleton,
    unavailability: unavailability,
    value: calendar,
    onChange: (nextCalendar, event) => {
      handleChange(_Finder2.VIEW.CALENDAR, nextCalendar, event);
      if (nextCalendar.length === 2 && !is.rates) {
        setError(_objectSpread(_objectSpread({}, error), {}, {
          calendar: undefined
        }));
        assistant();
      }
    },
    onError: calendar => setError(_objectSpread(_objectSpread({}, error), {}, {
      calendar
    })),
    onSubmit: is.rates ? handleSubmit : undefined,
    onValid: () => setError(_objectSpread(_objectSpread({}, error), {}, {
      calendar: undefined
    })),
    testId: others.testId ? "".concat(others.testId, "-calendar") : undefined
  }))), is.inline && /*#__PURE__*/_react.default.createElement(_ui.View, {
    className: style.separator
  }), /*#__PURE__*/_react.default.createElement(_shared__.FieldOccupation, _extends({
    dataSource: (0, _helpers.getOccupationDataSource)(_objectSpread(_objectSpread({}, dataSource), {}, {
      places: (_dataSource$places5 = dataSource.places) === null || _dataSource$places5 === void 0 ? void 0 : _dataSource$places5.options,
      place: place === null || place === void 0 ? void 0 : place.value
    })),
    hotels: (0, _helpers.getHotels)(dataSource.placesSource, place.value),
    maxRooms: dataSource.maxRooms,
    text: compacted ? text : undefined,
    value: occupation,
    visible: focus === _Finder2.VIEW.OCCUPATION,
    withWarning: warning,
    onChange: (occupation, event) => handleChange(_Finder2.VIEW.OCCUPATION, occupation, event),
    onError: occupation => {
      if (!isMobile && focus !== _Finder2.VIEW.OCCUPATION) setFocus(_Finder2.VIEW.OCCUPATION);
      setError(_objectSpread(_objectSpread({}, error), {}, {
        occupation
      }));
    },
    onPress: () => setFocus(focus !== _Finder2.VIEW.OCCUPATION ? _Finder2.VIEW.OCCUPATION : undefined),
    onSubmit: is.rates ? handleSubmit : isMobile && is.compacted ? () => setFocus() : undefined,
    onValid: () => setError(_objectSpread(_objectSpread({}, error), {}, {
      occupation: undefined
    })),
    onWarning: () => {
      if (focus !== _Finder2.VIEW.OCCUPATION) setFocus(_Finder2.VIEW.OCCUPATION);
    },
    testId: others.testId ? "".concat(others.testId, "-occupation") : undefined
  }, fieldProps)), is.inline && /*#__PURE__*/_react.default.createElement(_ui.View, {
    className: style.separator
  }), /*#__PURE__*/_react.default.createElement(_shared__.FieldPromocode, _extends({
    value: promocode,
    visible: focus === _Finder2.VIEW.PROMOCODE,
    onChange: (promocode, event) => handleChange(_Finder2.VIEW.PROMOCODE, promocode, event),
    onEnter: !is.compacted ? () => setFocus(_Finder2.VIEW.PROMOCODE) : undefined,
    onLeave: !is.compacted ? () => setFocus(undefined) : undefined,
    onPress: isMobile && is.compacted ? () => setFocus(focus !== _Finder2.VIEW.PROMOCODE ? _Finder2.VIEW.PROMOCODE : undefined) : undefined,
    onSubmit: isMobile && is.compacted ? is.rates ? handleSubmit : () => setFocus() : undefined,
    testId: others.testId ? "".concat(others.testId, "-promocode") : undefined
  }, fieldProps)), !is.compacted ? skeleton ? /*#__PURE__*/_react.default.createElement(_shared__.Skeleton, {
    large: true,
    button: true,
    words: 1
  }) : /*#__PURE__*/_react.default.createElement(_ui.Button, {
    disabled: skeleton,
    large: true,
    tabindex: 4,
    role: "finder-button",
    wide: is.column,
    onPress: handleSubmit,
    className: (0, _ui.styles)(style.button, icon && !is.column && style.withIcon),
    testId: others.testId ? "".concat(others.testId, "-submit") : undefined
  }, icon && !is.column ? /*#__PURE__*/_react.default.createElement(_ui.Icon, {
    value: _helpers3.ICON.SEARCH
  }) : text || translate(_Finder3.L10N.ACTION_SEARCH)) : null));
};
exports.Finder = Finder;
Finder.displayName = 'Mirai:Core:Finder';
Finder.propTypes = {
  compacted: _propTypes.default.bool,
  icon: _propTypes.default.bool,
  layout: _propTypes.default.oneOf(['column', 'expand']),
  storage: _propTypes.default.bool,
  text: _propTypes.default.string,
  onChange: _propTypes.default.func,
  onSubmit: _propTypes.default.func
};
//# sourceMappingURL=Finder.js.map