"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _react = _interopRequireWildcard(require("react"));
var _utils = require("./utils");
var _calendarContext = require("./calendar-context");
var _enums = require("./enums");
var _calendar = _interopRequireDefault(require("./components/calendar"));
var _dayjs = _interopRequireDefault(require("dayjs"));
var _localeData = _interopRequireDefault(require("dayjs/plugin/localeData"));
var _relativeTime = _interopRequireDefault(require("dayjs/plugin/relativeTime"));
var _localizedFormat = _interopRequireDefault(require("dayjs/plugin/localizedFormat"));
var _utc = _interopRequireDefault(require("dayjs/plugin/utc"));
var _timezone = _interopRequireDefault(require("dayjs/plugin/timezone"));
var _duration = _interopRequireDefault(require("dayjs/plugin/duration"));
var _usePrevious = require("./hooks/use-previous");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
_dayjs.default.extend(_localeData.default);
_dayjs.default.extend(_relativeTime.default);
_dayjs.default.extend(_localizedFormat.default);
_dayjs.default.extend(_utc.default);
_dayjs.default.extend(_timezone.default);
_dayjs.default.extend(_duration.default);
const DateTimePicker = props => {
  const {
    mode = 'single',
    locale = 'en',
    numerals = 'latn',
    timeZone,
    showOutsideDays = false,
    timePicker = false,
    firstDayOfWeek,
    // startYear,
    // endYear,
    minDate,
    maxDate,
    enabledDates,
    disabledDates,
    date,
    startDate,
    endDate,
    dates,
    min,
    max,
    onChange,
    initialView = 'day',
    containerHeight = _enums.CONTAINER_HEIGHT,
    weekdaysHeight = _enums.WEEKDAYS_HEIGHT,
    style = {},
    className = '',
    classNames = {},
    styles = {},
    navigationPosition,
    weekdaysFormat = 'min',
    monthsFormat = 'full',
    monthCaptionFormat = 'full',
    multiRangeMode,
    hideHeader,
    hideWeekdays,
    disableMonthPicker,
    disableYearPicker,
    components = {},
    month,
    year,
    onMonthChange = () => {},
    onYearChange = () => {},
    use12Hours
  } = props;
  _dayjs.default.tz.setDefault(timeZone);
  _dayjs.default.locale(locale);
  const prevTimezone = (0, _usePrevious.usePrevious)(timeZone);
  const initialCalendarView = (0, _react.useMemo)(() => mode !== 'single' && initialView === 'time' ? 'day' : initialView, [mode, initialView]);
  const firstDay = (0, _react.useMemo)(() => firstDayOfWeek && firstDayOfWeek > 0 && firstDayOfWeek <= 6 ? firstDayOfWeek : 0, [firstDayOfWeek]);
  const initialState = (0, _react.useMemo)(() => {
    let initialDate = (0, _dayjs.default)().tz(timeZone);
    if (mode === 'single' && date) {
      initialDate = (0, _dayjs.default)(date);
    }
    if (mode === 'range' && startDate) {
      initialDate = (0, _dayjs.default)(startDate);
    }
    if (mode === 'multiple' && dates && dates.length > 0) {
      initialDate = (0, _dayjs.default)(dates[0]);
    }
    if (minDate && initialDate.isBefore(minDate)) {
      initialDate = (0, _dayjs.default)(minDate);
    }
    if (month !== undefined && month && month >= 0 && month <= 11) {
      initialDate = initialDate.month(month);
    }
    if (year !== undefined && year >= 0) {
      initialDate = initialDate.year(year);
    }
    let _date = date ? (0, _dayjs.default)(date) : date;
    if (_date && maxDate && (0, _dayjs.default)(_date).isAfter(maxDate)) {
      _date = (0, _dayjs.default)(maxDate);
    }
    if (_date && minDate && (0, _dayjs.default)(_date).isBefore(minDate)) {
      _date = (0, _dayjs.default)(minDate);
    }
    let start = startDate ? (0, _dayjs.default)(startDate) : startDate;
    if (start && maxDate && (0, _dayjs.default)(start).isAfter(maxDate)) {
      start = (0, _dayjs.default)(maxDate);
    }
    if (start && minDate && (0, _dayjs.default)(start).isBefore(minDate)) {
      start = (0, _dayjs.default)(minDate);
    }
    let end = endDate ? (0, _dayjs.default)(endDate) : endDate;
    if (end && maxDate && (0, _dayjs.default)(end).isAfter(maxDate)) {
      end = (0, _dayjs.default)(maxDate);
    }
    if (end && minDate && (0, _dayjs.default)(end).isBefore(minDate)) {
      end = (0, _dayjs.default)(minDate);
    }
    return {
      date: _date,
      startDate: start,
      endDate: end,
      dates,
      calendarView: initialCalendarView,
      currentDate: initialDate,
      currentYear: initialDate.year()
    };
  }, [mode, date, startDate, endDate, dates, minDate, maxDate, month, year, timeZone, initialCalendarView]);
  const [state, dispatch] = (0, _react.useReducer)((prevState, action) => {
    switch (action.type) {
      case _enums.CalendarActionKind.SET_CALENDAR_VIEW:
        return {
          ...prevState,
          calendarView: action.payload
        };
      case _enums.CalendarActionKind.CHANGE_CURRENT_DATE:
        return {
          ...prevState,
          currentDate: action.payload
        };
      case _enums.CalendarActionKind.CHANGE_CURRENT_YEAR:
        return {
          ...prevState,
          currentYear: action.payload
        };
      case _enums.CalendarActionKind.CHANGE_SELECTED_DATE:
        const {
          date: selectedDate
        } = action.payload;
        return {
          ...prevState,
          date: selectedDate,
          currentDate: selectedDate
        };
      case _enums.CalendarActionKind.CHANGE_SELECTED_RANGE:
        const {
          startDate: start,
          endDate: end
        } = action.payload;
        return {
          ...prevState,
          startDate: start,
          endDate: end
        };
      case _enums.CalendarActionKind.CHANGE_SELECTED_MULTIPLE:
        const {
          dates: selectedDates
        } = action.payload;
        return {
          ...prevState,
          dates: selectedDates
        };
    }
  }, initialState);
  const stateRef = (0, _react.useRef)(state);
  stateRef.current = state;
  (0, _react.useEffect)(() => {
    if (prevTimezone !== timeZone) {
      const newDate = (0, _dayjs.default)().tz(timeZone);
      dispatch({
        type: _enums.CalendarActionKind.CHANGE_CURRENT_DATE,
        payload: newDate
      });
    }
  }, [timeZone, prevTimezone]);
  (0, _react.useEffect)(() => {
    if (mode === 'single') {
      let _date = (date && (timePicker ? _dayjs.default.tz(date, timeZone) : (0, _utils.getStartOfDay)(_dayjs.default.tz(date, timeZone)))) ?? date;
      if (_date && maxDate && _dayjs.default.tz(_date, timeZone).isAfter(maxDate)) {
        _date = _dayjs.default.tz(maxDate, timeZone);
      }
      if (_date && minDate && _dayjs.default.tz(_date, timeZone).isBefore(minDate)) {
        _date = _dayjs.default.tz(minDate, timeZone);
      }
      dispatch({
        type: _enums.CalendarActionKind.CHANGE_SELECTED_DATE,
        payload: {
          date: _date
        }
      });
      if (prevTimezone !== timeZone) {
        onChange({
          date: _date ? (0, _dayjs.default)(_date).toDate() : _date
        });
      }
    } else if (mode === 'range') {
      let start = startDate ? _dayjs.default.tz(startDate, timeZone) : startDate;
      if (start && maxDate && _dayjs.default.tz(start, timeZone).isAfter(maxDate)) {
        start = _dayjs.default.tz(maxDate, timeZone);
      }
      if (start && minDate && _dayjs.default.tz(start, timeZone).isBefore(minDate)) {
        start = _dayjs.default.tz(minDate, timeZone);
      }
      let end = endDate ? _dayjs.default.tz(endDate, timeZone) : endDate;
      if (end && maxDate && _dayjs.default.tz(end, timeZone).isAfter(maxDate)) {
        end = _dayjs.default.tz(maxDate, timeZone);
      }
      if (end && minDate && _dayjs.default.tz(end, timeZone).isBefore(minDate)) {
        end = _dayjs.default.tz(minDate, timeZone);
      }
      dispatch({
        type: _enums.CalendarActionKind.CHANGE_SELECTED_RANGE,
        payload: {
          startDate: start,
          endDate: end
        }
      });
      if (prevTimezone !== timeZone) {
        onChange({
          startDate: start ? (0, _dayjs.default)(start).toDate() : start,
          endDate: end ? (0, _dayjs.default)(end).toDate() : end
        });
      }
    } else if (mode === 'multiple') {
      const _dates = dates === null || dates === void 0 ? void 0 : dates.map(date => (0, _dayjs.default)(date).tz(timeZone));
      dispatch({
        type: _enums.CalendarActionKind.CHANGE_SELECTED_MULTIPLE,
        payload: {
          dates: _dates
        }
      });
      if (prevTimezone !== timeZone) {
        onChange({
          dates: _dates.map(item => (0, _dayjs.default)(item).toDate()),
          change: 'updated'
        });
      }
    }
  }, [mode, date, startDate, endDate, dates, minDate, maxDate, timePicker, prevTimezone, timeZone]);
  const setCalendarView = (0, _react.useCallback)(view => {
    dispatch({
      type: _enums.CalendarActionKind.SET_CALENDAR_VIEW,
      payload: view
    });
  }, []);
  const onSelectDate = (0, _react.useCallback)(selectedDate => {
    if (onChange) {
      if (mode === 'single') {
        const newDate = timePicker ? _dayjs.default.tz(selectedDate, timeZone) : _dayjs.default.tz((0, _utils.getStartOfDay)(selectedDate), timeZone);
        dispatch({
          type: _enums.CalendarActionKind.CHANGE_CURRENT_DATE,
          payload: newDate
        });
        onChange({
          date: newDate ? (0, _dayjs.default)(newDate).toDate() : newDate
        });
      } else if (mode === 'range') {
        // set time to 00:00:00
        let start = (0, _utils.removeTime)(stateRef.current.startDate, timeZone);
        let end = (0, _utils.removeTime)(stateRef.current.endDate, timeZone);
        const selected = (0, _utils.removeTime)(selectedDate, timeZone);
        let isStart = true;
        let isReset = false;
        if ((0, _utils.dateToUnix)(selected) !== (0, _utils.dateToUnix)(end) && (0, _utils.dateToUnix)(selected) >= (0, _utils.dateToUnix)(start) && (0, _utils.dateToUnix)(start) !== (0, _utils.dateToUnix)(end)) {
          isStart = false;
        } else if (start && (0, _utils.dateToUnix)(selected) === (0, _utils.dateToUnix)(start)) {
          isReset = true;
        }
        if (start && end) {
          if ((0, _utils.dateToUnix)(start) === (0, _utils.dateToUnix)(end) && (0, _utils.dateToUnix)(selected) > (0, _utils.dateToUnix)(start)) {
            isStart = false;
          }
          if ((0, _utils.dateToUnix)(selected) > (0, _utils.dateToUnix)(start) && (0, _utils.dateToUnix)(selected) === (0, _utils.dateToUnix)(end)) {
            end = undefined;
          }
        }
        if (start && !end && (0, _utils.dateToUnix)(selected) < (0, _utils.dateToUnix)(start)) {
          end = start;
        }
        if (isStart && end && (min || max)) {
          const numberOfDays = (0, _dayjs.default)(end).diff(selected, 'day');
          if (max && numberOfDays > max || min && numberOfDays < min) {
            isStart = true;
            end = undefined;
          }
        }
        if (!isStart && start && (min || max)) {
          const numberOfDays = (0, _dayjs.default)(selected).diff(start, 'day');
          if ((0, _utils.dateToUnix)(selected) === (0, _utils.dateToUnix)(start)) {
            isReset = true;
          } else if (max && numberOfDays > max || min && numberOfDays < min) {
            isStart = true;
            end = undefined;
          }
        }
        if (isReset) {
          onChange({
            startDate: undefined,
            endDate: undefined
          });
        } else {
          onChange({
            startDate: isStart ? (0, _dayjs.default)(selected).toDate() : start ? _dayjs.default.tz(start).toDate() : start,
            endDate: !isStart ? _dayjs.default.tz((0, _utils.getEndOfDay)(selected), timeZone).toDate() : end ? _dayjs.default.tz((0, _utils.getEndOfDay)(end), timeZone).toDate() : end
          });
        }
      } else if (mode === 'multiple') {
        const safeDates = stateRef.current.dates || [];
        const newDate = (0, _dayjs.default)(selectedDate, timeZone).startOf('day');
        const exists = safeDates.some(ed => (0, _utils.areDatesOnSameDay)(ed, newDate));
        const newDates = exists ? safeDates.filter(ed => !(0, _utils.areDatesOnSameDay)(ed, newDate)) : [...safeDates, newDate];
        if (max && newDates.length > max) {
          return;
        }
        newDates.sort((a, b) => (0, _dayjs.default)(a).isAfter((0, _dayjs.default)(b)) ? 1 : -1);
        const _dates = newDates.map(date => (0, _dayjs.default)(date).tz(timeZone));
        onChange({
          dates: _dates.map(item => (0, _dayjs.default)(item).toDate()),
          datePressed: newDate ? (0, _dayjs.default)(newDate).toDate() : newDate,
          change: exists ? 'removed' : 'added'
        });
      }
    }
  }, [mode, timePicker, min, max, timeZone]);

  // set the active displayed month
  const onSelectMonth = (0, _react.useCallback)(value => {
    const currentMonth = (0, _dayjs.default)(stateRef.current.currentDate).month();
    const newDate = (0, _dayjs.default)(stateRef.current.currentDate).month(value);

    // Only call onMonthChange if the month actually changed
    if (value !== currentMonth) {
      onMonthChange(value);
    }
    dispatch({
      type: _enums.CalendarActionKind.CHANGE_CURRENT_DATE,
      payload: newDate
    });
    setCalendarView('day');
  }, [setCalendarView, onMonthChange]);

  // set the active displayed year
  const onSelectYear = (0, _react.useCallback)(value => {
    const currentYear = (0, _dayjs.default)(stateRef.current.currentDate).year();
    const newDate = (0, _dayjs.default)(stateRef.current.currentDate).year(value);

    // Only call onYearChange if the year actually changed
    if (value !== currentYear) {
      onYearChange(value);
    }
    dispatch({
      type: _enums.CalendarActionKind.CHANGE_CURRENT_DATE,
      payload: newDate
    });
    setCalendarView('day');
  }, [setCalendarView, onYearChange]);
  const onChangeMonth = (0, _react.useCallback)(value => {
    const newDate = (0, _dayjs.default)(stateRef.current.currentDate).add(value, 'month');
    dispatch({
      type: _enums.CalendarActionKind.CHANGE_CURRENT_DATE,
      payload: (0, _dayjs.default)(newDate)
    });
  }, [stateRef, dispatch]);
  const onChangeYear = (0, _react.useCallback)(value => {
    dispatch({
      type: _enums.CalendarActionKind.CHANGE_CURRENT_YEAR,
      payload: value
    });
  }, [dispatch]);
  (0, _react.useEffect)(() => {
    if (month !== undefined && month >= 0 && month <= 11) {
      onSelectMonth(month);
    }
  }, [month]);
  (0, _react.useEffect)(() => {
    if (year !== undefined && year >= 0) {
      onSelectYear(year);
    }
  }, [year]);
  const memoizedStyles = (0, _utils.useDeepCompareMemo)({
    ...styles
  }, [styles]);
  const memoizedClassNames = (0, _utils.useDeepCompareMemo)({
    ...classNames
  }, [classNames]);
  const memoizedComponents = (0, _react.useMemo)(() => ({
    ...components
  }), [components]);
  const baseContextValue = (0, _react.useMemo)(() => ({
    mode,
    locale,
    numerals,
    timeZone,
    showOutsideDays,
    timePicker,
    minDate,
    maxDate,
    min,
    max,
    enabledDates,
    disabledDates,
    firstDayOfWeek: firstDay,
    containerHeight,
    weekdaysHeight,
    navigationPosition,
    weekdaysFormat,
    monthsFormat,
    monthCaptionFormat,
    multiRangeMode,
    hideHeader,
    hideWeekdays,
    disableMonthPicker,
    disableYearPicker,
    style,
    className,
    use12Hours
  }), [mode, locale, numerals, timeZone, showOutsideDays, timePicker, minDate, maxDate, min, max, enabledDates, disabledDates, firstDay, containerHeight, weekdaysHeight, navigationPosition, weekdaysFormat, monthsFormat, monthCaptionFormat, multiRangeMode, hideHeader, hideWeekdays, disableMonthPicker, disableYearPicker, style, className, use12Hours]);
  const handlerContextValue = (0, _react.useMemo)(() => ({
    setCalendarView,
    onSelectDate,
    onSelectMonth,
    onSelectYear,
    onChangeMonth,
    onChangeYear
  }), [setCalendarView, onSelectDate, onSelectMonth, onSelectYear, onChangeMonth, onChangeYear]);
  const styleContextValue = (0, _react.useMemo)(() => ({
    classNames: memoizedClassNames,
    styles: memoizedStyles
  }), [memoizedClassNames, memoizedStyles]);
  const memoizedValue = (0, _react.useMemo)(() => ({
    ...state,
    ...baseContextValue,
    ...handlerContextValue,
    ...styleContextValue,
    components: memoizedComponents
  }), [state, baseContextValue, handlerContextValue, styleContextValue, memoizedComponents]);
  return /*#__PURE__*/_react.default.createElement(_calendarContext.CalendarContext.Provider, {
    value: memoizedValue
  }, /*#__PURE__*/_react.default.createElement(_calendar.default, null));
};
var _default = exports.default = DateTimePicker;
//# sourceMappingURL=datetime-picker.js.map