import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
import _extends from "@babel/runtime/helpers/esm/extends";
var _excluded = ["parentProps", "day", "focusableDay", "selectedDays", "isDateDisabled", "currentMonthNumber", "isViewFocused"],
  _excluded2 = ["ownerState"];
import * as React from 'react';
import useEventCallback from '@mui/utils/useEventCallback';
import Typography from '@mui/material/Typography';
import { useSlotProps } from '@mui/base/utils';
import { styled, useTheme, useThemeProps } from '@mui/material/styles';
import { unstable_composeClasses as composeClasses, unstable_useControlled as useControlled } from '@mui/utils';
import clsx from 'clsx';
import { PickersDay } from '../PickersDay/PickersDay';
import { useUtils, useNow, useLocaleText } from '../internals/hooks/useUtils';
import { DAY_SIZE, DAY_MARGIN } from '../internals/constants/dimensions';
import { PickersSlideTransition } from './PickersSlideTransition';
import { useIsDateDisabled } from './useIsDateDisabled';
import { findClosestEnabledDate } from '../internals/utils/date-utils';
import { getDayCalendarUtilityClass } from './dayCalendarClasses';
import { jsx as _jsx } from "react/jsx-runtime";
import { jsxs as _jsxs } from "react/jsx-runtime";
var useUtilityClasses = function useUtilityClasses(ownerState) {
  var classes = ownerState.classes;
  var slots = {
    header: ['header'],
    weekDayLabel: ['weekDayLabel'],
    loadingContainer: ['loadingContainer'],
    slideTransition: ['slideTransition'],
    monthContainer: ['monthContainer'],
    weekContainer: ['weekContainer'],
    weekNumberLabel: ['weekNumberLabel'],
    weekNumber: ['weekNumber']
  };
  return composeClasses(slots, getDayCalendarUtilityClass, classes);
};
var defaultDayOfWeekFormatter = function defaultDayOfWeekFormatter(day) {
  return day.charAt(0).toUpperCase();
};
var weeksContainerHeight = (DAY_SIZE + DAY_MARGIN * 2) * 6;
var PickersCalendarDayHeader = styled('div', {
  name: 'MuiDayCalendar',
  slot: 'Header',
  overridesResolver: function overridesResolver(_, styles) {
    return styles.header;
  }
})({
  display: 'flex',
  justifyContent: 'center',
  alignItems: 'center'
});
var PickersCalendarWeekDayLabel = styled(Typography, {
  name: 'MuiDayCalendar',
  slot: 'WeekDayLabel',
  overridesResolver: function overridesResolver(_, styles) {
    return styles.weekDayLabel;
  }
})(function (_ref) {
  var theme = _ref.theme;
  return {
    width: 36,
    height: 40,
    margin: '0 2px',
    textAlign: 'center',
    display: 'flex',
    justifyContent: 'center',
    alignItems: 'center',
    color: (theme.vars || theme).palette.text.secondary
  };
});
var PickersCalendarWeekNumberLabel = styled(Typography, {
  name: 'MuiDayPicker',
  slot: 'WeekNumberLabel',
  overridesResolver: function overridesResolver(_, styles) {
    return styles.weekNumberLabel;
  }
})(function (_ref2) {
  var theme = _ref2.theme;
  return {
    width: 36,
    height: 40,
    margin: '0 2px',
    textAlign: 'center',
    display: 'flex',
    justifyContent: 'center',
    alignItems: 'center',
    color: theme.palette.text.disabled
  };
});
var PickersCalendarWeekNumber = styled(Typography, {
  name: 'MuiDayPicker',
  slot: 'WeekNumber',
  overridesResolver: function overridesResolver(_, styles) {
    return styles.weekNumber;
  }
})(function (_ref3) {
  var theme = _ref3.theme;
  return _extends({}, theme.typography.caption, {
    width: DAY_SIZE,
    height: DAY_SIZE,
    padding: 0,
    margin: "0 ".concat(DAY_MARGIN, "px"),
    color: theme.palette.text.disabled,
    fontSize: '0.75rem',
    alignItems: 'center',
    justifyContent: 'center',
    display: 'inline-flex'
  });
});
var PickersCalendarLoadingContainer = styled('div', {
  name: 'MuiDayCalendar',
  slot: 'LoadingContainer',
  overridesResolver: function overridesResolver(_, styles) {
    return styles.loadingContainer;
  }
})({
  display: 'flex',
  justifyContent: 'center',
  alignItems: 'center',
  minHeight: weeksContainerHeight
});
var PickersCalendarSlideTransition = styled(PickersSlideTransition, {
  name: 'MuiDayCalendar',
  slot: 'SlideTransition',
  overridesResolver: function overridesResolver(_, styles) {
    return styles.slideTransition;
  }
})({
  minHeight: weeksContainerHeight
});
var PickersCalendarWeekContainer = styled('div', {
  name: 'MuiDayCalendar',
  slot: 'MonthContainer',
  overridesResolver: function overridesResolver(_, styles) {
    return styles.monthContainer;
  }
})({
  overflow: 'hidden'
});
var PickersCalendarWeek = styled('div', {
  name: 'MuiDayCalendar',
  slot: 'WeekContainer',
  overridesResolver: function overridesResolver(_, styles) {
    return styles.weekContainer;
  }
})({
  margin: "".concat(DAY_MARGIN, "px 0"),
  display: 'flex',
  justifyContent: 'center'
});
function WrappedDay(_ref4) {
  var _ref5, _slots$day, _slotProps$day;
  var parentProps = _ref4.parentProps,
    day = _ref4.day,
    focusableDay = _ref4.focusableDay,
    selectedDays = _ref4.selectedDays,
    isDateDisabled = _ref4.isDateDisabled,
    currentMonthNumber = _ref4.currentMonthNumber,
    isViewFocused = _ref4.isViewFocused,
    other = _objectWithoutProperties(_ref4, _excluded);
  var disabled = parentProps.disabled,
    disableHighlightToday = parentProps.disableHighlightToday,
    isMonthSwitchingAnimating = parentProps.isMonthSwitchingAnimating,
    showDaysOutsideCurrentMonth = parentProps.showDaysOutsideCurrentMonth,
    components = parentProps.components,
    componentsProps = parentProps.componentsProps,
    slots = parentProps.slots,
    slotProps = parentProps.slotProps,
    timezone = parentProps.timezone;
  var utils = useUtils();
  var now = useNow(timezone);
  var isFocusableDay = focusableDay !== null && utils.isSameDay(day, focusableDay);
  var isSelected = selectedDays.some(function (selectedDay) {
    return utils.isSameDay(selectedDay, day);
  });
  var isToday = utils.isSameDay(day, now);
  var Day = (_ref5 = (_slots$day = slots == null ? void 0 : slots.day) != null ? _slots$day : components == null ? void 0 : components.Day) != null ? _ref5 : PickersDay;
  // We don't want to pass to ownerState down, to avoid re-rendering all the day whenever a prop changes.
  var _useSlotProps = useSlotProps({
      elementType: Day,
      externalSlotProps: (_slotProps$day = slotProps == null ? void 0 : slotProps.day) != null ? _slotProps$day : componentsProps == null ? void 0 : componentsProps.day,
      additionalProps: _extends({
        disableHighlightToday: disableHighlightToday,
        showDaysOutsideCurrentMonth: showDaysOutsideCurrentMonth,
        role: 'gridcell',
        isAnimating: isMonthSwitchingAnimating,
        // it is used in date range dragging logic by accessing `dataset.timestamp`
        'data-timestamp': utils.toJsDate(day).valueOf()
      }, other),
      ownerState: _extends({}, parentProps, {
        day: day,
        selected: isSelected
      })
    }),
    dayOwnerState = _useSlotProps.ownerState,
    dayProps = _objectWithoutProperties(_useSlotProps, _excluded2);
  var isDisabled = React.useMemo(function () {
    return disabled || isDateDisabled(day);
  }, [disabled, isDateDisabled, day]);
  var outsideCurrentMonth = React.useMemo(function () {
    return utils.getMonth(day) !== currentMonthNumber;
  }, [utils, day, currentMonthNumber]);
  var isFirstVisibleCell = React.useMemo(function () {
    var startOfMonth = utils.startOfMonth(utils.setMonth(day, currentMonthNumber));
    if (!showDaysOutsideCurrentMonth) {
      return utils.isSameDay(day, startOfMonth);
    }
    return utils.isSameDay(day, utils.startOfWeek(startOfMonth));
  }, [currentMonthNumber, day, showDaysOutsideCurrentMonth, utils]);
  var isLastVisibleCell = React.useMemo(function () {
    var endOfMonth = utils.endOfMonth(utils.setMonth(day, currentMonthNumber));
    if (!showDaysOutsideCurrentMonth) {
      return utils.isSameDay(day, endOfMonth);
    }
    return utils.isSameDay(day, utils.endOfWeek(endOfMonth));
  }, [currentMonthNumber, day, showDaysOutsideCurrentMonth, utils]);
  return /*#__PURE__*/_jsx(Day, _extends({}, dayProps, {
    day: day,
    disabled: isDisabled,
    autoFocus: isViewFocused && isFocusableDay,
    today: isToday,
    outsideCurrentMonth: outsideCurrentMonth,
    isFirstVisibleCell: isFirstVisibleCell,
    isLastVisibleCell: isLastVisibleCell,
    selected: isSelected,
    tabIndex: isFocusableDay ? 0 : -1,
    "aria-selected": isSelected,
    "aria-current": isToday ? 'date' : undefined
  }));
}

/**
 * @ignore - do not document.
 */
export function DayCalendar(inProps) {
  var props = useThemeProps({
    props: inProps,
    name: 'MuiDayCalendar'
  });
  var onFocusedDayChange = props.onFocusedDayChange,
    className = props.className,
    currentMonth = props.currentMonth,
    selectedDays = props.selectedDays,
    focusedDay = props.focusedDay,
    loading = props.loading,
    onSelectedDaysChange = props.onSelectedDaysChange,
    onMonthSwitchingAnimationEnd = props.onMonthSwitchingAnimationEnd,
    readOnly = props.readOnly,
    reduceAnimations = props.reduceAnimations,
    _props$renderLoading = props.renderLoading,
    renderLoading = _props$renderLoading === void 0 ? function () {
      return /*#__PURE__*/_jsx("span", {
        children: "..."
      });
    } : _props$renderLoading,
    slideDirection = props.slideDirection,
    TransitionProps = props.TransitionProps,
    disablePast = props.disablePast,
    disableFuture = props.disableFuture,
    minDate = props.minDate,
    maxDate = props.maxDate,
    shouldDisableDate = props.shouldDisableDate,
    shouldDisableMonth = props.shouldDisableMonth,
    shouldDisableYear = props.shouldDisableYear,
    _props$dayOfWeekForma = props.dayOfWeekFormatter,
    dayOfWeekFormatter = _props$dayOfWeekForma === void 0 ? defaultDayOfWeekFormatter : _props$dayOfWeekForma,
    hasFocus = props.hasFocus,
    onFocusedViewChange = props.onFocusedViewChange,
    gridLabelId = props.gridLabelId,
    displayWeekNumber = props.displayWeekNumber,
    fixedWeekNumber = props.fixedWeekNumber,
    autoFocus = props.autoFocus,
    timezone = props.timezone;
  var now = useNow(timezone);
  var utils = useUtils();
  var classes = useUtilityClasses(props);
  var theme = useTheme();
  var isRTL = theme.direction === 'rtl';
  var isDateDisabled = useIsDateDisabled({
    shouldDisableDate: shouldDisableDate,
    shouldDisableMonth: shouldDisableMonth,
    shouldDisableYear: shouldDisableYear,
    minDate: minDate,
    maxDate: maxDate,
    disablePast: disablePast,
    disableFuture: disableFuture,
    timezone: timezone
  });
  var localeText = useLocaleText();
  var _useControlled = useControlled({
      name: 'DayCalendar',
      state: 'hasFocus',
      controlled: hasFocus,
      default: autoFocus != null ? autoFocus : false
    }),
    _useControlled2 = _slicedToArray(_useControlled, 2),
    internalHasFocus = _useControlled2[0],
    setInternalHasFocus = _useControlled2[1];
  var _React$useState = React.useState(function () {
      return focusedDay || now;
    }),
    _React$useState2 = _slicedToArray(_React$useState, 2),
    internalFocusedDay = _React$useState2[0],
    setInternalFocusedDay = _React$useState2[1];
  var handleDaySelect = useEventCallback(function (day) {
    if (readOnly) {
      return;
    }
    onSelectedDaysChange(day);
  });
  var focusDay = function focusDay(day) {
    if (!isDateDisabled(day)) {
      onFocusedDayChange(day);
      setInternalFocusedDay(day);
      onFocusedViewChange == null || onFocusedViewChange(true);
      setInternalHasFocus(true);
    }
  };
  var handleKeyDown = useEventCallback(function (event, day) {
    switch (event.key) {
      case 'ArrowUp':
        focusDay(utils.addDays(day, -7));
        event.preventDefault();
        break;
      case 'ArrowDown':
        focusDay(utils.addDays(day, 7));
        event.preventDefault();
        break;
      case 'ArrowLeft':
        {
          var newFocusedDayDefault = utils.addDays(day, isRTL ? 1 : -1);
          var nextAvailableMonth = utils.addMonths(day, isRTL ? 1 : -1);
          var closestDayToFocus = findClosestEnabledDate({
            utils: utils,
            date: newFocusedDayDefault,
            minDate: isRTL ? newFocusedDayDefault : utils.startOfMonth(nextAvailableMonth),
            maxDate: isRTL ? utils.endOfMonth(nextAvailableMonth) : newFocusedDayDefault,
            isDateDisabled: isDateDisabled,
            timezone: timezone
          });
          focusDay(closestDayToFocus || newFocusedDayDefault);
          event.preventDefault();
          break;
        }
      case 'ArrowRight':
        {
          var _newFocusedDayDefault = utils.addDays(day, isRTL ? -1 : 1);
          var _nextAvailableMonth = utils.addMonths(day, isRTL ? -1 : 1);
          var _closestDayToFocus = findClosestEnabledDate({
            utils: utils,
            date: _newFocusedDayDefault,
            minDate: isRTL ? utils.startOfMonth(_nextAvailableMonth) : _newFocusedDayDefault,
            maxDate: isRTL ? _newFocusedDayDefault : utils.endOfMonth(_nextAvailableMonth),
            isDateDisabled: isDateDisabled,
            timezone: timezone
          });
          focusDay(_closestDayToFocus || _newFocusedDayDefault);
          event.preventDefault();
          break;
        }
      case 'Home':
        focusDay(utils.startOfWeek(day));
        event.preventDefault();
        break;
      case 'End':
        focusDay(utils.endOfWeek(day));
        event.preventDefault();
        break;
      case 'PageUp':
        focusDay(utils.addMonths(day, 1));
        event.preventDefault();
        break;
      case 'PageDown':
        focusDay(utils.addMonths(day, -1));
        event.preventDefault();
        break;
      default:
        break;
    }
  });
  var handleFocus = useEventCallback(function (event, day) {
    return focusDay(day);
  });
  var handleBlur = useEventCallback(function (event, day) {
    if (internalHasFocus && utils.isSameDay(internalFocusedDay, day)) {
      onFocusedViewChange == null || onFocusedViewChange(false);
    }
  });
  var currentMonthNumber = utils.getMonth(currentMonth);
  var validSelectedDays = React.useMemo(function () {
    return selectedDays.filter(function (day) {
      return !!day;
    }).map(function (day) {
      return utils.startOfDay(day);
    });
  }, [utils, selectedDays]);

  // need a new ref whenever the `key` of the transition changes: http://reactcommunity.org/react-transition-group/transition/#Transition-prop-nodeRef.
  var transitionKey = currentMonthNumber;
  // eslint-disable-next-line react-hooks/exhaustive-deps
  var slideNodeRef = React.useMemo(function () {
    return /*#__PURE__*/React.createRef();
  }, [transitionKey]);
  var startOfCurrentWeek = utils.startOfWeek(now);
  var focusableDay = React.useMemo(function () {
    var startOfMonth = utils.startOfMonth(currentMonth);
    var endOfMonth = utils.endOfMonth(currentMonth);
    if (isDateDisabled(internalFocusedDay) || utils.isAfterDay(internalFocusedDay, endOfMonth) || utils.isBeforeDay(internalFocusedDay, startOfMonth)) {
      return findClosestEnabledDate({
        utils: utils,
        date: internalFocusedDay,
        minDate: startOfMonth,
        maxDate: endOfMonth,
        disablePast: disablePast,
        disableFuture: disableFuture,
        isDateDisabled: isDateDisabled,
        timezone: timezone
      });
    }
    return internalFocusedDay;
  }, [currentMonth, disableFuture, disablePast, internalFocusedDay, isDateDisabled, utils, timezone]);
  var weeksToDisplay = React.useMemo(function () {
    var currentMonthWithTimezone = utils.setTimezone(currentMonth, timezone);
    var toDisplay = utils.getWeekArray(currentMonthWithTimezone);
    var nextMonth = utils.addMonths(currentMonthWithTimezone, 1);
    while (fixedWeekNumber && toDisplay.length < fixedWeekNumber) {
      var additionalWeeks = utils.getWeekArray(nextMonth);
      var hasCommonWeek = utils.isSameDay(toDisplay[toDisplay.length - 1][0], additionalWeeks[0][0]);
      additionalWeeks.slice(hasCommonWeek ? 1 : 0).forEach(function (week) {
        if (toDisplay.length < fixedWeekNumber) {
          toDisplay.push(week);
        }
      });
      nextMonth = utils.addMonths(nextMonth, 1);
    }
    return toDisplay;
  }, [currentMonth, fixedWeekNumber, utils, timezone]);
  return /*#__PURE__*/_jsxs("div", {
    role: "grid",
    "aria-labelledby": gridLabelId,
    children: [/*#__PURE__*/_jsxs(PickersCalendarDayHeader, {
      role: "row",
      className: classes.header,
      children: [displayWeekNumber && /*#__PURE__*/_jsx(PickersCalendarWeekNumberLabel, {
        variant: "caption",
        role: "columnheader",
        "aria-label": localeText.calendarWeekNumberHeaderLabel,
        className: classes.weekNumberLabel,
        children: localeText.calendarWeekNumberHeaderText
      }), utils.getWeekdays().map(function (day, i) {
        var _dayOfWeekFormatter;
        return /*#__PURE__*/_jsx(PickersCalendarWeekDayLabel, {
          variant: "caption",
          role: "columnheader",
          "aria-label": utils.format(utils.addDays(startOfCurrentWeek, i), 'weekday'),
          className: classes.weekDayLabel,
          children: (_dayOfWeekFormatter = dayOfWeekFormatter == null ? void 0 : dayOfWeekFormatter(day)) != null ? _dayOfWeekFormatter : day
        }, day + i.toString());
      })]
    }), loading ? /*#__PURE__*/_jsx(PickersCalendarLoadingContainer, {
      className: classes.loadingContainer,
      children: renderLoading()
    }) : /*#__PURE__*/_jsx(PickersCalendarSlideTransition, _extends({
      transKey: transitionKey,
      onExited: onMonthSwitchingAnimationEnd,
      reduceAnimations: reduceAnimations,
      slideDirection: slideDirection,
      className: clsx(className, classes.slideTransition)
    }, TransitionProps, {
      nodeRef: slideNodeRef,
      children: /*#__PURE__*/_jsx(PickersCalendarWeekContainer, {
        ref: slideNodeRef,
        role: "rowgroup",
        className: classes.monthContainer,
        children: weeksToDisplay.map(function (week, index) {
          return /*#__PURE__*/_jsxs(PickersCalendarWeek, {
            role: "row",
            className: classes.weekContainer
            // fix issue of announcing row 1 as row 2
            // caused by week day labels row
            ,
            "aria-rowindex": index + 1,
            children: [displayWeekNumber && /*#__PURE__*/_jsx(PickersCalendarWeekNumber, {
              className: classes.weekNumber,
              role: "rowheader",
              "aria-label": localeText.calendarWeekNumberAriaLabelText(utils.getWeekNumber(week[0])),
              children: localeText.calendarWeekNumberText(utils.getWeekNumber(week[0]))
            }), week.map(function (day, dayIndex) {
              return /*#__PURE__*/_jsx(WrappedDay, {
                parentProps: props,
                day: day,
                selectedDays: validSelectedDays,
                focusableDay: focusableDay,
                onKeyDown: handleKeyDown,
                onFocus: handleFocus,
                onBlur: handleBlur,
                onDaySelect: handleDaySelect,
                isDateDisabled: isDateDisabled,
                currentMonthNumber: currentMonthNumber,
                isViewFocused: internalHasFocus
                // fix issue of announcing column 1 as column 2 when `displayWeekNumber` is enabled
                ,
                "aria-colindex": dayIndex + 1
              }, day.toString());
            })]
          }, "week-".concat(week[0]));
        })
      })
    }))]
  });
}