import { useEffect, useState, useCallback } from 'react';
import '../common/theme.mjs';
import '../common/direction.mjs';
import '@transferwise/neptune-tokens';
import '../common/propsValues/control.mjs';
import '../common/propsValues/size.mjs';
import '../common/propsValues/typography.mjs';
import '../common/propsValues/width.mjs';
import '../common/propsValues/type.mjs';
import '../common/propsValues/dateMode.mjs';
import { MonthFormat } from '../common/propsValues/monthFormat.mjs';
import '../common/propsValues/position.mjs';
import '../common/propsValues/layouts.mjs';
import '../common/propsValues/status.mjs';
import '../common/propsValues/sentiment.mjs';
import '../common/propsValues/profileType.mjs';
import '../common/propsValues/variant.mjs';
import '../common/propsValues/scroll.mjs';
import '../common/propsValues/markdownNodeType.mjs';
import '../common/fileType.mjs';
import '@transferwise/formatting';
import '@transferwise/icons';
import 'clsx';
import 'react-intl';
import '../common/closeButton/CloseButton.messages.mjs';
import { jsxs, jsx } from 'react/jsx-runtime';
import { moveToWithinRange } from '../common/dateUtils/moveToWithinRange/moveToWithinRange.mjs';
import { isWithinRange } from '../common/dateUtils/isWithinRange/isWithinRange.mjs';
import { returnDateView } from '../common/dateUtils/getDateView/getDateView.mjs';
import DayCalendar from './dayCalendar/DayCalendar.mjs';
import { getStartOfDay } from './getStartOfDay/getStartOfDay.mjs';
import MonthCalendar from './monthCalendar/MonthCalendar.mjs';
import YearCalendar from './yearCalendar/YearCalendar.mjs';

const Calendar = ({
  value,
  min: minProp = null,
  max: maxProp = null,
  monthFormat = MonthFormat.LONG,
  placeholder,
  onChange,
  onSelect
}) => {
  const selectedDate = getStartOfDay(value);
  const min = getStartOfDay(minProp);
  const max = getStartOfDay(maxProp);
  useEffect(() => {
    if (selectedDate && !isWithinRange(selectedDate, min, max)) {
      onChange(moveToWithinRange(selectedDate, min, max));
    }
  }, [selectedDate?.getTime(), min?.getTime(), max?.getTime(), onChange]); // eslint-disable-line react-hooks/exhaustive-deps
  const dateView = returnDateView(selectedDate, min, max);
  const [viewMonth, setViewMonth] = useState(dateView.getMonth());
  const [viewYear, setViewYear] = useState(dateView.getFullYear());
  const [mode, setMode] = useState('day');
  useEffect(() => {
    const view = returnDateView(selectedDate, min, max);
    // eslint-disable-next-line react-hooks/set-state-in-effect
    setViewMonth(view.getMonth());
    setViewYear(view.getFullYear());
  }, [selectedDate?.getTime(), min?.getTime(), max?.getTime()]); // eslint-disable-line react-hooks/exhaustive-deps
  const handleViewDateUpdate = useCallback(
  // eslint-disable-next-line react-hooks/preserve-manual-memoization
  ({
    month,
    year
  }) => {
    if (month !== undefined) setViewMonth(month);
    if (year !== undefined) setViewYear(year);
  }, []);
  const switchToDays = useCallback(() => setMode('day'), []);
  const switchToMonths = useCallback(() => setMode('month'), []);
  const switchToYears = useCallback(() => setMode('year'), []);
  const handleSelectedDateUpdate = useCallback(date => {
    if (onSelect) {
      onSelect(date);
    } else {
      onChange(date);
    }
  }, [onChange, onSelect]);
  const adjustDate = useCallback((daysToAdd, monthsToAdd, yearsToAdd) => {
    let date;
    if (selectedDate) {
      date = new Date(mode === 'year' ? selectedDate.getFullYear() + yearsToAdd : selectedDate.getFullYear(), mode === 'month' ? selectedDate.getMonth() + monthsToAdd : selectedDate.getMonth(), mode === 'day' ? selectedDate.getDate() + daysToAdd : selectedDate.getDate());
    } else {
      date = getStartOfDay(new Date());
    }
    date &&= moveToWithinRange(date, min, max);
    if (date?.getTime() !== selectedDate?.getTime()) {
      onChange(date);
    }
  }, [selectedDate, min, max, mode, onChange]);
  const handleKeyDown = useCallback(event => {
    switch (event.key) {
      case 'ArrowLeft':
        adjustDate(-1, -1, -1);
        event.preventDefault();
        break;
      case 'ArrowUp':
        adjustDate(-7, -4, -4);
        event.preventDefault();
        break;
      case 'ArrowRight':
        adjustDate(1, 1, 1);
        event.preventDefault();
        break;
      case 'ArrowDown':
        adjustDate(7, 4, 4);
        event.preventDefault();
        break;
    }
  }, [adjustDate]);
  return (
    /*#__PURE__*/
    // eslint-disable-next-line jsx-a11y/no-static-element-interactions
    jsxs("div", {
      onKeyDown: handleKeyDown,
      children: [mode === 'day' && /*#__PURE__*/jsx(DayCalendar, {
        selectedDate: selectedDate,
        min: min,
        max: max,
        viewMonth: viewMonth,
        viewYear: viewYear,
        monthFormat: monthFormat,
        onSelect: handleSelectedDateUpdate,
        onLabelClick: switchToYears,
        onViewDateUpdate: handleViewDateUpdate
      }), mode === 'month' && /*#__PURE__*/jsx(MonthCalendar, {
        selectedDate: selectedDate,
        min: min,
        max: max,
        viewYear: viewYear,
        ...(placeholder != null && {
          placeholder
        }),
        onSelect: switchToDays,
        onLabelClick: switchToYears,
        onViewDateUpdate: handleViewDateUpdate
      }), mode === 'year' && /*#__PURE__*/jsx(YearCalendar, {
        selectedDate: selectedDate,
        min: min,
        max: max,
        viewYear: viewYear,
        ...(placeholder != null && {
          placeholder
        }),
        onSelect: switchToMonths,
        onViewDateUpdate: handleViewDateUpdate
      })]
    })
  );
};

export { Calendar as default };
//# sourceMappingURL=Calendar.mjs.map
