import React, { useEffect, useState, useCallback } from 'react';
import { View } from 'react-native';
import dayjs from 'dayjs';
import localeData from 'dayjs/plugin/localeData';
import localizedFormat from 'dayjs/plugin/localizedFormat';
import utc from 'dayjs/plugin/utc';
import { getSurroundingTimeUnits } from '../Utils';
import { useSurroundingTimeUnits } from '../Hooks';
import { ThemeContext, LocaleContext } from '../Contexts';
import { VIEW } from '../Constants';
import { Months, Days, Arrow as DefaultArrow, Title as DefaultTitle, Weekdays as DefaultWeekdays, } from '../Components';
dayjs.extend(localeData);
dayjs.extend(localizedFormat);
dayjs.extend(utc);
const BaseCalendar = ({ ArrowComponent: CustomArrow, TitleComponent: CustomTitle, WeekdaysComponent: CustomWeekdays, DayComponent, MonthComponent, allowYearView, showExtraDates, onPressDay, maxDate, minDate, initVisibleDate, dateProperties, testID, }) => {
    const theme = React.useContext(ThemeContext);
    const locale = React.useContext(LocaleContext);
    const [rightArrowDisabled, disableRightArrow] = useState(false);
    const [leftArrowDisabled, disableLeftArrow] = useState(false);
    const [activeView, setActiveView] = useState(VIEW.MONTH);
    const [visibleDate, setVisibleDate] = useState(initVisibleDate ?? dayjs().local().format());
    const localeAwareVisibleDate = React.useMemo(() => dayjs(visibleDate).locale(locale.name, locale), [locale, visibleDate]);
    const weekdays = React.useMemo(() => locale.weekdaysShort ?? [''], [locale]);
    const { month, year } = useSurroundingTimeUnits(visibleDate);
    const verifyUnitIsPastMaxDate = useCallback((unit) => {
        if (maxDate) {
            if (unit.isAfter(maxDate)) {
                disableRightArrow(true);
            }
            else {
                disableRightArrow(false);
            }
        }
    }, [disableRightArrow, maxDate]);
    const verifyUnitIsBeforeMinDate = useCallback((unit) => {
        if (minDate) {
            if (unit.isBefore(minDate)) {
                disableLeftArrow(true);
            }
            else {
                disableLeftArrow(false);
            }
        }
    }, [disableLeftArrow, minDate]);
    const toggleCalendarView = useCallback((newVisibleDate = visibleDate) => {
        const { month: _month, year: _year } = getSurroundingTimeUnits(newVisibleDate);
        if (activeView === VIEW.MONTH) {
            setActiveView(VIEW.YEAR);
            verifyUnitIsPastMaxDate(_year.next);
            verifyUnitIsBeforeMinDate(_year.last);
        }
        if (activeView === VIEW.YEAR) {
            setActiveView(VIEW.MONTH);
            verifyUnitIsPastMaxDate(_month.next);
            verifyUnitIsBeforeMinDate(_month.last);
        }
    }, [activeView, verifyUnitIsBeforeMinDate, verifyUnitIsPastMaxDate, visibleDate]);
    useEffect(() => {
        verifyUnitIsPastMaxDate(month.next.start);
        verifyUnitIsBeforeMinDate(month.last.end);
    }, [
        month.last.end,
        month.next.start,
        verifyUnitIsPastMaxDate,
        verifyUnitIsBeforeMinDate,
    ]);
    const addMonth = useCallback(() => {
        setVisibleDate(month.next.start.local().format());
        verifyUnitIsPastMaxDate(month.afterNext);
        verifyUnitIsBeforeMinDate(month.current.end);
    }, [month, verifyUnitIsBeforeMinDate, verifyUnitIsPastMaxDate]);
    const subtractMonth = useCallback(() => {
        setVisibleDate(month.last.start.local().format());
        verifyUnitIsPastMaxDate(month.current.start);
        verifyUnitIsBeforeMinDate(month.beforeLast);
    }, [month, verifyUnitIsBeforeMinDate, verifyUnitIsPastMaxDate]);
    const addYear = useCallback(() => {
        setVisibleDate(year.next.persistMonth.local().format());
        verifyUnitIsPastMaxDate(year.afterNext);
        verifyUnitIsBeforeMinDate(year.current.end);
    }, [year, verifyUnitIsBeforeMinDate, verifyUnitIsPastMaxDate]);
    const subtractYear = useCallback(() => {
        setVisibleDate(year.last.persistMonth.local().format());
        verifyUnitIsPastMaxDate(year.current.start);
        verifyUnitIsBeforeMinDate(year.beforeLast);
    }, [year, verifyUnitIsBeforeMinDate, verifyUnitIsPastMaxDate]);
    const onPressMonth = (newVisibleDate) => {
        setVisibleDate(newVisibleDate);
        toggleCalendarView(newVisibleDate);
    };
    const Weekdays = CustomWeekdays || DefaultWeekdays;
    const Arrow = CustomArrow || DefaultArrow;
    const Title = CustomTitle || DefaultTitle;
    return (<View style={theme.calendarContainer} testID={testID}>
      <View testID={'header'} style={theme.headerContainer}>
        <Arrow direction={'left'} isDisabled={leftArrowDisabled} onPress={activeView === VIEW.MONTH ? subtractMonth : subtractYear}/>
        <Title activeView={activeView} locale={locale} date={localeAwareVisibleDate.format('YYYY-MM-DD')} isDisabled={!allowYearView} onPress={toggleCalendarView}/>
        <Arrow direction={'right'} isDisabled={rightArrowDisabled} onPress={activeView === VIEW.MONTH ? addMonth : addYear}/>
      </View>
      {activeView === VIEW.MONTH ? (<>
          <Weekdays days={weekdays}/>
          <Days DayComponent={DayComponent} visibleDate={localeAwareVisibleDate} showExtraDates={!!showExtraDates} dateProperties={dateProperties} onPressDay={onPressDay} minDate={minDate} maxDate={maxDate}/>
        </>) : (<Months MonthComponent={MonthComponent} visibleDate={localeAwareVisibleDate} minDate={minDate ? dayjs(minDate).local().format() : undefined} maxDate={maxDate ? dayjs(maxDate).local().format() : undefined} dateProperties={dateProperties} onPressMonth={onPressMonth}/>)}
    </View>);
};
export default BaseCalendar;
//# sourceMappingURL=BaseCalendar.js.map