/* eslint-disable no-plusplus */
import React, { 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';
var CalenderMonth = /*#__PURE__*/forwardRef(function (props, ref) {
  var _useState = useState(),
      visible = _useState[0],
      setVisible = _useState[1];

  var daysRef = useRef();

  var _useState2 = useState(),
      monthRef = _useState2[0],
      setMonthRef = _useState2[1];

  var height = useRef(0);

  var _useContext = useContext(ConfigProviderContext),
      prefixCls = _useContext.prefixCls,
      createNamespace = _useContext.createNamespace,
      locale = _useContext.locale;

  var _createNamespace = createNamespace('calendar', prefixCls),
      bem = _createNamespace[0];

  useEffect(function () {
    if (monthRef) {
      height.current = getRect(monthRef).height;
    }
  }, [monthRef]);
  var title = useMemo(function () {
    var _locale$vanCalendar;

    return props.formatMonthTitle ? props.formatMonthTitle(props.date) : (_locale$vanCalendar = locale.vanCalendar).monthTitle.apply(_locale$vanCalendar, formatMonthTitle(props.date));
  }, [props.date, props.formatMonthTitle]);
  var rowHeight = useMemo(function () {
    return addUnit(props.rowHeight);
  }, [props.rowHeight]);
  var offset = useMemo(function () {
    var realDay = props.date.getDay();

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

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

  var getTitle = function getTitle() {
    return title;
  };

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

  var getMultipleDayType = function getMultipleDayType(day) {
    var isSelected = function isSelected(date) {
      return props.currentDate.some(function (item) {
        return compareDay(item, date) === 0;
      });
    };

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

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

      if (prevSelected) {
        return 'end';
      }

      if (nextSelected) {
        return 'start';
      }

      return 'multiple-selected';
    }

    return '';
  };

  var getRangeDayType = function getRangeDayType(day) {
    var _ref = props.currentDate,
        startDay = _ref[0],
        endDay = _ref[1];

    if (!startDay) {
      return '';
    }

    var compareToStart = compareDay(day, startDay);

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

    var 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 '';
  };

  var getDayType = function getDayType(day) {
    var type = props.type,
        minDate = props.minDate,
        maxDate = props.maxDate,
        currentDate = props.currentDate;

    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 '';
  };

  var getBottomInfo = function 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;
  };

  var renderTitle = function renderTitle() {
    if (props.showMonthTitle) {
      return /*#__PURE__*/React.createElement("div", {
        className: cls(bem('month-title'))
      }, title);
    }

    return null;
  };

  var renderMark = function renderMark() {
    if (props.showMark && shouldRender) {
      return /*#__PURE__*/React.createElement("div", {
        className: cls(bem('month-mark'))
      }, props.date.getMonth() + 1);
    }

    return null;
  };

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

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

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

      internalDays.push(config);
    }

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

  var renderDay = function renderDay(item, index) {
    return /*#__PURE__*/React.createElement(CalendarDay, {
      key: index,
      item: item,
      index: index,
      color: props.color,
      offset: offset,
      rowHeight: rowHeight,
      onClick: props.onClick,
      topInfoRender: props.topInfoRender,
      bottomInfoRender: props.bottomInfoRender
    });
  };

  var renderDays = function renderDays() {
    return /*#__PURE__*/React.createElement("div", {
      ref: daysRef,
      role: "grid",
      className: cls(bem('days'))
    }, renderMark(), (shouldRender ? days : placeholders).map(renderDay));
  };

  useImperativeHandle(ref, function () {
    return {
      getTitle: getTitle,
      getHeight: function getHeight() {
        return height.current;
      },
      setVisible: setVisible,
      scrollIntoView: scrollIntoView
    };
  });
  return /*#__PURE__*/React.createElement("div", {
    className: cls(bem('month')),
    ref: setMonthRef
  }, renderTitle(), renderDays());
});
export default CalenderMonth;