import _extends from "@babel/runtime/helpers/esm/extends";
import React, { useState, useCallback, useMemo, useEffect } from "react";
import { SwitchTransition } from "react-transition-group";
import { addMonths, isAfter } from "date-fns";
import moment from "moment";
import { customClassNames, modifiersClassNames } from "./ClassNames";
import { CustomNavBarElement } from "./CustomNavBarElement";
import { StyledDatePicker, StyledDatePickerCSSTransition, StyledDayPicker } from "./Styles";
import { YearMonthPicker } from "../Pickers/YearMonthPicker";
const formatWeekdayName = str => moment(str).format("ddd").charAt(0);
export const DatePicker = _ref => {
  let {
    className,
    onChange,
    onDayClick,
    selectedDays,
    disabledDays,
    selectionMode = "daily",
    month = new Date(),
    onMonthChange = () => null,
    dateRequired = false,
    firstDayOfWeek = 0,
    fixedWeeks = true,
    modifiers: defaultModifiers,
    renderDay,
    ...rest
  } = _ref;
  const [enteredTo, setEnteredTo] = useState();
  const [enteredFrom, setEnteredFrom] = useState();
  const [stopScroll, setStopScroll] = useState();
  const [direction, setDirection] = useState(true);
  const [isPreselected, setIsPreselected] = useState(() => {
    return (selectedDays == null ? void 0 : selectedDays.from) instanceof Date && (selectedDays == null ? void 0 : selectedDays.to) instanceof Date;
  });
  const [showMonthPicker, setShowMonthPicker] = useState(selectionMode === "quarterly" || selectionMode === "monthly");
  const [modifiers, setModifiers] = useState(defaultModifiers);
  const week = firstDayOfWeek === 0 ? "week" : "isoWeek";
  useEffect(() => {
    if (enteredFrom instanceof Date && enteredTo instanceof Date) {
      setModifiers(prev => {
        return {
          ...prev,
          hovered: {
            from: enteredFrom,
            to: enteredTo
          }
        };
      });
    } else {
      setModifiers(defaultModifiers);
    }
  }, [enteredTo, enteredFrom, defaultModifiers]);
  const handleDayClick = useCallback((day, modifiers) => {
    if (onDayClick) {
      onDayClick(day, modifiers);
    }
    if (!onChange) {
      return;
    }
    if (month.getMonth() !== day.getMonth()) {
      onMonthChange(day);
    }
    if (modifiers["day_disabled"] || selectionMode === "none") {
      return;
    }
    // reset the selectedDays if the user clicks on the same day
    if (!dateRequired && (selectedDays != null && selectedDays.from && moment(day).isSame(moment(selectedDays.from), "day") || selectedDays != null && selectedDays.to && moment(day).isSame(moment(selectedDays.to), "day"))) {
      setEnteredTo(undefined);
      setEnteredFrom(undefined);
      return onChange(undefined);
    }
    if (selectionMode === "daily") {
      return onChange({
        from: day,
        to: day
      });
    }
    if (selectionMode === "weekly") {
      if (!dateRequired && selectedDays != null && selectedDays.from && moment(day).isSame(moment(selectedDays.from), week)) {
        return onChange(undefined);
      }
      return onChange({
        from: moment(day).startOf(week).toDate(),
        to: moment(day).endOf(week).toDate()
      });
    }
    if (selectionMode === "custom") {
      if (isPreselected) {
        setIsPreselected(false);
        return onChange({
          from: day,
          to: day
        });
      }
      if (!selectedDays || selectedDays != null && selectedDays.from && selectedDays != null && selectedDays.to && !moment(selectedDays.from).isSame(moment(selectedDays.to))) {
        if (!dateRequired && selectedDays != null && selectedDays.from && selectedDays != null && selectedDays.to && moment(day).isBetween(moment(selectedDays.from), moment(selectedDays.to))) {
          setEnteredTo(day);
          setEnteredFrom(day);
          return onChange(undefined);
        }
        setEnteredFrom(day);
        return onChange({
          from: day,
          to: day
        });
      }
      if (selectedDays != null && selectedDays.from && isAfter(day, selectedDays.from)) {
        setEnteredTo(undefined);
        setEnteredFrom(undefined);
        return onChange({
          from: selectedDays.from,
          to: day
        });
      }
      if (selectedDays != null && selectedDays.to) {
        setEnteredTo(undefined);
        setEnteredFrom(undefined);
        return onChange({
          from: day,
          to: selectedDays.to
        });
      }
      return onChange({
        from: day,
        to: day
      });
    }
  }, [onDayClick, onChange, month, selectionMode, dateRequired, selectedDays, onMonthChange, week, isPreselected]);
  const isSelectedFirstDay = useCallback(() => {
    if (selectionMode !== "custom") {
      return false;
    }
    if (selectedDays != null && selectedDays.from && selectedDays != null && selectedDays.to) {
      return moment(selectedDays.from).isSame(selectedDays.to);
    }
  }, [selectionMode, selectedDays]);
  const handleDayMouseEnter = useCallback(day => {
    if (isPreselected && selectionMode !== "weekly") {
      setEnteredTo(day);
      setEnteredFrom(day);
      return;
    }
    if (selectionMode === "daily") {
      setEnteredTo(day);
      setEnteredFrom(day);
    }
    if (selectionMode === "weekly") {
      setEnteredFrom(moment(day).startOf(week).toDate());
      setEnteredTo(moment(day).endOf(week).toDate());
    }
    if (selectionMode !== "weekly" && (!selectedDays || selectedDays != null && selectedDays.from && selectedDays != null && selectedDays.to && !moment(selectedDays.from).isSame(moment(selectedDays.to)))) {
      setEnteredTo(day);
      setEnteredFrom(day);
    }
    if (isSelectedFirstDay() && selectedDays != null && selectedDays.from) {
      setEnteredFrom(selectedDays.from);
      setEnteredTo(day);
    }
  }, [selectionMode, isSelectedFirstDay, selectedDays, week, isPreselected]);
  const onDayMouseLeave = useCallback(() => {
    if (selectionMode === "weekly" || selectionMode === "daily" || selectionMode === "custom") {
      setEnteredFrom(undefined);
      setEnteredTo(undefined);
    }
  }, [setEnteredFrom, setEnteredTo, selectionMode]);
  const onWheel = useCallback(e => {
    if (stopScroll && (new Date().getTime() - stopScroll.getTime()) / 1000 < 0.9) {
      return;
    }
    const nextMonth = showMonthPicker ? addMonths(month, 12) : addMonths(month, 1);
    const previousMonth = showMonthPicker ? addMonths(month, -12) : addMonths(month, -1);
    if (e.deltaY > 0.9) {
      setDirection(true);
      onMonthChange(nextMonth);
      setStopScroll(new Date());
    }
    if (e.deltaY < -0.9) {
      setDirection(false);
      onMonthChange(previousMonth);
      setStopScroll(new Date());
    }
  }, [stopScroll, showMonthPicker, month, onMonthChange]);
  const togglePicker = useCallback(() => {
    if (selectionMode !== "monthly" && selectionMode !== "quarterly") {
      return setShowMonthPicker(!showMonthPicker);
    }
    setShowMonthPicker(true);
  }, [showMonthPicker, selectionMode]);
  const handleYearMonthChange = useCallback(m => {
    if (onChange) {
      if (selectionMode === "monthly") {
        if (!dateRequired && selectedDays != null && selectedDays.from && moment(m).isSame(moment(selectedDays.from), "month")) {
          return onChange(undefined);
        }
        onChange({
          from: moment(m).startOf("month").toDate(),
          to: moment(m).endOf("month").toDate()
        });
      }
      if (selectionMode === "quarterly") {
        if (!dateRequired && selectedDays != null && selectedDays.from && moment(m).isSame(moment(selectedDays.from).startOf("quarter"), "quarter")) {
          return onChange(undefined);
        }
        onChange({
          from: moment(m).startOf("quarter").toDate(),
          to: moment(m).endOf("quarter").toDate()
        });
      }
    }
    onMonthChange(m);
  }, [onMonthChange, onChange, selectedDays, selectionMode, dateRequired]);
  const text = useMemo(() => {
    if (showMonthPicker) {
      return "" + month.getFullYear();
    }
    return moment(month).format("MMMM") + " " + (moment(month).isSame(moment(), "year") ? "" : month.getFullYear());
  }, [showMonthPicker, month]);
  const customNavBarElement = useCallback(props => {
    return /*#__PURE__*/React.createElement("div", {
      className: "c-DayPicker-wrapper"
    }, /*#__PURE__*/React.createElement(CustomNavBarElement, _extends({}, props, {
      showMonthPicker: showMonthPicker,
      month: month,
      onChangeDirection: setDirection,
      onMonthChange: onMonthChange,
      onClick: togglePicker
    })), /*#__PURE__*/React.createElement(YearMonthPicker, _extends({}, props, {
      text: text,
      onClick: togglePicker,
      month: month,
      selectedDays: selectedDays,
      onChange: handleYearMonthChange,
      isShown: showMonthPicker,
      selectionMode: selectionMode
    })));
  }, [showMonthPicker, month, onMonthChange, togglePicker, text, selectedDays, handleYearMonthChange, selectionMode]);
  const onKeyDownCallback = useCallback(e => {
    // Right Arrow
    if (e.key === "ArrowRight") {
      setDirection(true);
      if (showMonthPicker) {
        onMonthChange(new Date(month.getFullYear() + 1, month.getMonth()));
      } else {
        onMonthChange(new Date(month.getFullYear(), month.getMonth() + 1));
      }
    }
    // Left Arrow
    if (e.key === "ArrowLeft") {
      setDirection(false);
      if (showMonthPicker) {
        onMonthChange(new Date(month.getFullYear() - 1, month.getMonth()));
      } else {
        onMonthChange(new Date(month.getFullYear(), month.getMonth() - 1));
      }
    }
    // Up Arrow
    if (e.key === "ArrowUp") {
      setDirection(true);
      onMonthChange(new Date(month.getFullYear() + 1, month.getMonth()));
    }
    // Down Arrow
    if (e.key === "ArrowDown") {
      setDirection(false);
      onMonthChange(new Date(month.getFullYear() - 1, month.getMonth()));
    }
  }, [showMonthPicker, onMonthChange, month]);
  useEffect(() => {
    document.addEventListener("keydown", onKeyDownCallback);
    return () => {
      document.removeEventListener("keydown", onKeyDownCallback);
    };
  }, [month, onMonthChange, showMonthPicker, onKeyDownCallback]);
  const selected = useMemo(() => {
    const dates = [];
    if (!(selectedDays != null && selectedDays.from)) return [];

    // If from and to dates are the same, return an array with one item
    if (moment(selectedDays == null ? void 0 : selectedDays.from).isSame(selectedDays == null ? void 0 : selectedDays.to, "day")) {
      dates.push(selectedDays == null ? void 0 : selectedDays.from);
      return dates;
    }
    let currentDate = moment(selectedDays == null ? void 0 : selectedDays.from);
    while (currentDate.isSameOrBefore(selectedDays == null ? void 0 : selectedDays.to, "day")) {
      dates.push(currentDate.toDate());
      currentDate = currentDate.add(1, "days");
    }
    return dates;
  }, [selectedDays == null ? void 0 : selectedDays.from, selectedDays == null ? void 0 : selectedDays.to]);
  return /*#__PURE__*/React.createElement(StyledDatePicker, {
    className: "c-date-picker-wrapper",
    onWheel: onWheel
  }, /*#__PURE__*/React.createElement(SwitchTransition, {
    mode: "out-in"
  }, /*#__PURE__*/React.createElement(StyledDatePickerCSSTransition, {
    key: showMonthPicker ? month.getFullYear() : month.getMonth(),
    timeout: 300,
    classNames: "c-date-picker__animation",
    $direction: direction
  }, /*#__PURE__*/React.createElement(StyledDayPicker, _extends({}, rest, {
    mode: "multiple",
    showOutsideDays: true,
    disabled: disabledDays,
    selected: selected,
    onDayClick: handleDayClick,
    modifiers: modifiers,
    onDayMouseEnter: handleDayMouseEnter,
    onDayMouseLeave: onDayMouseLeave,
    className: className,
    $isYearlyView: showMonthPicker,
    month: month,
    components: {
      Caption: customNavBarElement,
      DayContent: renderDay
    },
    classNames: customClassNames,
    modifiersClassNames: modifiersClassNames,
    fixedWeeks: fixedWeeks,
    weekStartsOn: firstDayOfWeek,
    formatters: {
      formatWeekdayName: formatWeekdayName
    }
  })))));
};
DatePicker.displayName = "DatePicker";
//# sourceMappingURL=DatePicker.js.map