import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
/* eslint-disable no-plusplus */

import { forwardRef, useContext, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
import cls from 'clsx';
import { addUnit, setScrollTop } from '../utils';
import { compareDay, formatMonthTitle, getNextDay, getPrevDay } from './utils';
import { getMonthEndDay } from '../datetime-picker/utils';
import CalendarDay from './CalendarDay';
import { getRect } from '../hooks/use-rect';
import ConfigProviderContext from '../config-provider/ConfigProviderContext';
const CalenderMonth = forwardRef((props, ref) => {
  const [visible, setVisible] = useState();
  const daysRef = useRef();
  const [monthRef, setMonthRef] = useState();
  const height = useRef(0);
  const {
    prefixCls,
    createNamespace,
    locale
  } = useContext(ConfigProviderContext);
  const [bem] = createNamespace('calendar', prefixCls);
  useEffect(() => {
    if (monthRef) {
      height.current = getRect(monthRef).height;
    }
  }, [monthRef]);
  const title = useMemo(() => {
    return props.formatMonthTitle ? props.formatMonthTitle(props.date) : locale.vanCalendar.monthTitle(...formatMonthTitle(props.date));
  }, [props.date, props.formatMonthTitle]);
  const rowHeight = useMemo(() => addUnit(props.rowHeight), [props.rowHeight]);
  const offset = useMemo(() => {
    const realDay = props.date.getDay();

    if (props.firstDayOfWeek) {
      return (realDay + 7 - props.firstDayOfWeek) % 7;
    }

    return realDay;
  }, [props.date, props.firstDayOfWeek]);
  const totalDay = useMemo(() => getMonthEndDay(props.date.getFullYear(), props.date.getMonth() + 1), [props.date]);
  const shouldRender = useMemo(() => visible || !props.lazyRender, [visible]);

  const getTitle = () => title;

  const scrollIntoView = body => {
    const el = props.showSubtitle ? daysRef.current : monthRef;
    const scrollTop = el.getBoundingClientRect().top - body.getBoundingClientRect().top + body.scrollTop;
    setScrollTop(body, scrollTop);
  };

  const getMultipleDayType = day => {
    const isSelected = date => props.currentDate.some(item => compareDay(item, date) === 0);

    if (isSelected(day)) {
      const prevDay = getPrevDay(day);
      const nextDay = getNextDay(day);
      const prevSelected = isSelected(prevDay);
      const nextSelected = isSelected(nextDay);

      if (prevSelected && nextSelected) {
        return 'multiple-middle';
      }

      if (prevSelected) {
        return 'end';
      }

      if (nextSelected) {
        return 'start';
      }

      return 'multiple-selected';
    }

    return '';
  };

  const getRangeDayType = day => {
    const [startDay, endDay] = props.currentDate;

    if (!startDay) {
      return '';
    }

    const compareToStart = compareDay(day, startDay);

    if (!endDay) {
      return compareToStart === 0 ? 'start' : '';
    }

    const compareToEnd = compareDay(day, endDay);

    if (props.allowSameDay && compareToStart === 0 && compareToEnd === 0) {
      return 'start-end';
    }

    if (compareToStart === 0) {
      return 'start';
    }

    if (compareToEnd === 0) {
      return 'end';
    }

    if (compareToStart > 0 && compareToEnd < 0) {
      return 'middle';
    }

    return '';
  };

  const getDayType = day => {
    const {
      type,
      minDate,
      maxDate,
      currentDate
    } = props;

    if (compareDay(day, minDate) < 0 || compareDay(day, maxDate) > 0) {
      return 'disabled';
    }

    if (currentDate === null) {
      return '';
    }

    if (Array.isArray(currentDate)) {
      if (type === 'multiple') {
        return getMultipleDayType(day);
      }

      if (type === 'range') {
        return getRangeDayType(day);
      }
    } else if (type === 'single') {
      return compareDay(day, currentDate) === 0 ? 'selected' : '';
    }

    return '';
  };

  const getBottomInfo = dayType => {
    if (props.type === 'range') {
      if (dayType === 'start') {
        return locale.vanCalendar.start;
      }

      if (dayType === 'end') {
        return locale.vanCalendar.end;
      }

      if (dayType === 'start-end') {
        return locale.vanCalendar.startEnd;
      }
    }

    return null;
  };

  const renderTitle = () => {
    if (props.showMonthTitle) {
      return _jsx("div", Object.assign({
        className: cls(bem('month-title'))
      }, {
        children: title
      }));
    }

    return null;
  };

  const renderMark = () => {
    if (props.showMark && shouldRender) {
      return _jsx("div", Object.assign({
        className: cls(bem('month-mark'))
      }, {
        children: props.date.getMonth() + 1
      }));
    }

    return null;
  };

  const placeholders = useMemo(() => {
    const count = Math.ceil((totalDay + offset) / 7);
    return Array(count).fill({
      type: 'placeholder'
    });
  }, [totalDay, offset]);
  const days = useMemo(() => {
    const internalDays = [];
    const year = props.date.getFullYear();
    const month = props.date.getMonth();

    for (let day = 1; day <= totalDay; day++) {
      const date = new Date(year, month, day);
      const type = getDayType(date);
      let config = {
        date,
        type,
        text: day,
        bottomInfo: getBottomInfo(type)
      };

      if (props.formatter) {
        config = props.formatter(config);
      }

      internalDays.push(config);
    }

    return internalDays;
  }, [getDayType, props.date, props.formatter]);

  const renderDay = (item, index) => _jsx(CalendarDay, {
    item: item,
    index: index,
    color: props.color,
    offset: offset,
    rowHeight: rowHeight,
    onClick: props.onClick,
    topInfoRender: props.topInfoRender,
    bottomInfoRender: props.bottomInfoRender
  }, index);

  const renderDays = () => _jsxs("div", Object.assign({
    ref: daysRef,
    role: "grid",
    className: cls(bem('days'))
  }, {
    children: [renderMark(), (shouldRender ? days : placeholders).map(renderDay)]
  }));

  useImperativeHandle(ref, () => ({
    getTitle,
    getHeight: () => height.current,
    setVisible,
    scrollIntoView
  }));
  return _jsxs("div", Object.assign({
    className: cls(bem('month')),
    ref: setMonthRef
  }, {
    children: [renderTitle(), renderDays()]
  }));
});
export default CalenderMonth;