import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
import _extends from "@babel/runtime/helpers/esm/extends";
import * as React from 'react';
import useEventCallback from '@mui/utils/useEventCallback';
import { useIsDateDisabled } from './useIsDateDisabled';
import { useUtils, useNow } from '../internals/hooks/useUtils';
import { singleItemValueManager } from '../internals/utils/valueManagers';
import { SECTION_TYPE_GRANULARITY } from '../internals/utils/getDefaultReferenceDate';
export var createCalendarStateReducer = function createCalendarStateReducer(reduceAnimations, disableSwitchToMonthOnDayFocus, utils) {
  return function (state, action) {
    switch (action.type) {
      case 'changeMonth':
        return _extends({}, state, {
          slideDirection: action.direction,
          currentMonth: action.newMonth,
          isMonthSwitchingAnimating: !reduceAnimations
        });
      case 'finishMonthSwitchingAnimation':
        return _extends({}, state, {
          isMonthSwitchingAnimating: false
        });
      case 'changeFocusedDay':
        {
          if (state.focusedDay != null && action.focusedDay != null && utils.isSameDay(action.focusedDay, state.focusedDay)) {
            return state;
          }
          var needMonthSwitch = action.focusedDay != null && !disableSwitchToMonthOnDayFocus && !utils.isSameMonth(state.currentMonth, action.focusedDay);
          return _extends({}, state, {
            focusedDay: action.focusedDay,
            isMonthSwitchingAnimating: needMonthSwitch && !reduceAnimations && !action.withoutMonthSwitchingAnimation,
            currentMonth: needMonthSwitch ? utils.startOfMonth(action.focusedDay) : state.currentMonth,
            slideDirection: action.focusedDay != null && utils.isAfterDay(action.focusedDay, state.currentMonth) ? 'left' : 'right'
          });
        }
      default:
        throw new Error('missing support');
    }
  };
};
export var useCalendarState = function useCalendarState(params) {
  var value = params.value,
    referenceDateProp = params.referenceDate,
    defaultCalendarMonth = params.defaultCalendarMonth,
    disableFuture = params.disableFuture,
    disablePast = params.disablePast,
    _params$disableSwitch = params.disableSwitchToMonthOnDayFocus,
    disableSwitchToMonthOnDayFocus = _params$disableSwitch === void 0 ? false : _params$disableSwitch,
    maxDate = params.maxDate,
    minDate = params.minDate,
    onMonthChange = params.onMonthChange,
    reduceAnimations = params.reduceAnimations,
    shouldDisableDate = params.shouldDisableDate,
    timezone = params.timezone;
  var now = useNow(timezone);
  var utils = useUtils();
  var reducerFn = React.useRef(createCalendarStateReducer(Boolean(reduceAnimations), disableSwitchToMonthOnDayFocus, utils)).current;
  var referenceDate = React.useMemo(function () {
    var externalReferenceDate = null;
    if (referenceDateProp) {
      externalReferenceDate = referenceDateProp;
    } else if (defaultCalendarMonth) {
      // For `defaultCalendarMonth`, we just want to keep the month and the year to avoid a behavior change.
      externalReferenceDate = utils.startOfMonth(defaultCalendarMonth);
    }
    return singleItemValueManager.getInitialReferenceValue({
      value: value,
      utils: utils,
      timezone: timezone,
      props: params,
      referenceDate: externalReferenceDate,
      granularity: SECTION_TYPE_GRANULARITY.day
    });
  }, [] // eslint-disable-line react-hooks/exhaustive-deps
  );

  var _React$useReducer = React.useReducer(reducerFn, {
      isMonthSwitchingAnimating: false,
      focusedDay: value || now,
      currentMonth: utils.startOfMonth(referenceDate),
      slideDirection: 'left'
    }),
    _React$useReducer2 = _slicedToArray(_React$useReducer, 2),
    calendarState = _React$useReducer2[0],
    dispatch = _React$useReducer2[1];
  var handleChangeMonth = React.useCallback(function (payload) {
    dispatch(_extends({
      type: 'changeMonth'
    }, payload));
    if (onMonthChange) {
      onMonthChange(payload.newMonth);
    }
  }, [onMonthChange]);
  var changeMonth = React.useCallback(function (newDate) {
    var newDateRequested = newDate;
    if (utils.isSameMonth(newDateRequested, calendarState.currentMonth)) {
      return;
    }
    handleChangeMonth({
      newMonth: utils.startOfMonth(newDateRequested),
      direction: utils.isAfterDay(newDateRequested, calendarState.currentMonth) ? 'left' : 'right'
    });
  }, [calendarState.currentMonth, handleChangeMonth, utils]);
  var isDateDisabled = useIsDateDisabled({
    shouldDisableDate: shouldDisableDate,
    minDate: minDate,
    maxDate: maxDate,
    disableFuture: disableFuture,
    disablePast: disablePast,
    timezone: timezone
  });
  var onMonthSwitchingAnimationEnd = React.useCallback(function () {
    dispatch({
      type: 'finishMonthSwitchingAnimation'
    });
  }, []);
  var changeFocusedDay = useEventCallback(function (newFocusedDate, withoutMonthSwitchingAnimation) {
    if (!isDateDisabled(newFocusedDate)) {
      dispatch({
        type: 'changeFocusedDay',
        focusedDay: newFocusedDate,
        withoutMonthSwitchingAnimation: withoutMonthSwitchingAnimation
      });
    }
  });
  return {
    referenceDate: referenceDate,
    calendarState: calendarState,
    changeMonth: changeMonth,
    changeFocusedDay: changeFocusedDay,
    isDateDisabled: isDateDisabled,
    onMonthSwitchingAnimationEnd: onMonthSwitchingAnimationEnd,
    handleChangeMonth: handleChangeMonth
  };
};