import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useEffect, useRef, useState } from 'react';
import Box from '../box';
import { omitThemingProps, useStyleConfig, vui } from '../core';
import { cs } from '../utils';
import { CalendarHeader, DayPicker, MonthPicker, YearPicker } from './components';
import { useCalendar, useDefaultViewMonth } from './hooks';
import { isDay, isExact, isFrom, isMonth, isTo, isYear, processSelectMonth, processSelectYear, processViewDate, } from './utils';
/** Displays calendar. */
export const Calendar = vui((props, ref) => {
    const { boundaries, className, fixedNumberOfWeeks = false, disabled, isStartDate, mode, onSelectDates, selectedDates, ...rest } = omitThemingProps(props);
    const styles = useStyleConfig('Calendar', props);
    const currentDateRef = useRef(isFrom(mode) || isExact(mode) ? selectedDates?.startDate : selectedDates?.endDate);
    /**
     * Effect to reset viewDate when selectedDates changes (onReset)
     */
    useEffect(() => {
        currentDateRef.current = isFrom(mode) || isExact(mode) ? selectedDates?.startDate : selectedDates?.endDate;
        currentDateRef.current && setViewDate(currentDateRef.current);
    }, [selectedDates]);
    const calendarRef = useRef(null);
    const defaultViewMonth = useDefaultViewMonth({
        boundaries,
        selectedDate: currentDateRef.current,
        isStartDate,
    });
    const [timeUnitMode, setTimeUnitMode] = useState('day');
    const [viewDate, setViewDate] = useState(defaultViewMonth);
    /**
     * Handles clicking next/prev in header
     */
    const onChangeViewItem = (direction) => {
        const newViewMonth = processViewDate(viewDate, direction, timeUnitMode, calendarRef?.current?.items);
        newViewMonth && setViewDate(newViewMonth);
    };
    /**
     * Handles clicking on a day
     */
    const onSelectDay = (clickedDate) => () => {
        updateDateState(clickedDate);
        setViewDate(clickedDate);
    };
    /**
     * Handles clicking on a month
     */
    const onSelectMonth = (clickedDate) => () => {
        const processedNewDate = processSelectMonth(clickedDate, mode, boundaries);
        updateDateState(processedNewDate);
        setViewDate(processedNewDate);
        setTimeUnitMode('day');
    };
    /**
     * Handles clicking on a year
     */
    const onSelectYear = (clickedDate) => () => {
        const processedNewDate = processSelectYear(clickedDate, mode, boundaries);
        updateDateState(processedNewDate);
        setViewDate(processedNewDate);
        setTimeUnitMode('month');
    };
    /**
     * Send update date to parent component
     */
    const updateDateState = (newDate) => {
        const dateRange = { ...selectedDates };
        if (dateRange) {
            if (isTo(mode))
                dateRange.endDate = newDate;
            else
                dateRange.startDate = newDate;
        }
        if (newDate && !disabled)
            onSelectDates && onSelectDates(dateRange);
    };
    const calendar = (calendarRef.current = useCalendar({
        boundaries,
        mode,
        selectedDates,
        timeUnitMode,
        viewDate,
        fixedNumberOfWeeks,
    }));
    return (_jsxs(Box, { className: cs('vui-calendar', className), column: true, cursor: "default", minW: 280, position: "relative", ref: ref, w: "fit-content", ...styles, ...rest, children: [_jsx(CalendarHeader, { nextDisabled: calendar.nextDisabled, onChangeViewItem: onChangeViewItem, onSetTimeUnitMode: (mode) => setTimeUnitMode(mode), prevDisabled: calendar.prevDisabled, timeUnitMode: timeUnitMode, viewMonth: viewDate }), isDay(timeUnitMode) && _jsx(DayPicker, { calendar: calendar, onSelectDay: onSelectDay }), isMonth(timeUnitMode) && _jsx(MonthPicker, { calendar: calendar, onSelectMonth: onSelectMonth }), isYear(timeUnitMode) && _jsx(YearPicker, { calendar: calendar, onSelectYear: onSelectYear })] }));
});
Calendar.displayName = 'Calendar';
export default Calendar;
//# sourceMappingURL=calendar.js.map