import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

import { createBEM } from '@zarm-design/bem';
import dayjs from 'dayjs';
import throttle from 'lodash/throttle';
import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
import { Transition } from 'react-transition-group';
import Carousel from '../carousel';
import { ConfigContext } from '../config-provider';
import useScroll from '../use-scroll';
import { getElementSize } from '../utils/dom';
import Header from './Header';
import CalendarMonthView from './Month';
import parseState from './utils/parseState';
import Week from './Week';
var Calendar = /*#__PURE__*/React.forwardRef(function (props, ref) {
  var className = props.className,
      dateRender = props.dateRender,
      disabledDate = props.disabledDate,
      onChange = props.onChange,
      mode = props.mode,
      maxDate = props.max,
      minDate = props.min,
      direction = props.direction,
      header = props.header;
  var container = ref || /*#__PURE__*/React.createRef();

  var _useContext = useContext(ConfigContext),
      prefixCls = _useContext.prefixCls;

  var carouselRef = useRef(null);
  var bem = createBEM('calendar', {
    prefixCls: prefixCls
  });
  var cls = bem([className]);

  var _useState = useState(function () {
    return _objectSpread(_objectSpread({}, parseState(props)), {}, {
      step: 0
    });
  }),
      _useState2 = _slicedToArray(_useState, 2),
      state = _useState2[0],
      setState = _useState2[1];

  var min = state.min,
      max = state.max,
      value = state.value;
  var nodes = useRef({});
  var scrollBodyRef = /*#__PURE__*/React.createRef();
  var weekRef = React.useRef();

  var _useState3 = useState(),
      _useState4 = _slicedToArray(_useState3, 2),
      scrollDate = _useState4[0],
      setScrollDate = _useState4[1];

  var _useState5 = useState(false),
      _useState6 = _slicedToArray(_useState5, 2),
      scrolling = _useState6[0],
      setScrolling = _useState6[1];

  var isHorizontal = useMemo(function () {
    return direction === 'horizontal';
  }, [direction]);
  var months = useMemo(function () {
    var month = [];
    var dateMax = dayjs(max);
    var dateMin = dayjs(min);
    var len = (dateMax.year() - dateMin.year()) * 12 + dateMax.month() - dateMin.month();
    var i = 0;

    do {
      month.push(dayjs(min).add(i, 'month').toDate());
      i += 1;
    } while (i <= len);

    return month;
  }, [state.max, state.min]);
  var currentMonthIndex = useMemo(function () {
    var currentTime = dayjs(value[0] || new Date());
    return months.findIndex(function (current) {
      return dayjs(current).isSame(currentTime, 'month');
    });
  }, [state.value]);

  var _useState7 = useState(currentMonthIndex),
      _useState8 = _slicedToArray(_useState7, 2),
      currentMonth = _useState8[0],
      setCurrentMonth = _useState8[1]; // 月历定位


  var scrollIntoView = useRef(false);

  var anchor = function anchor() {
    var target = value[0] || new Date();
    var key = "".concat(target.getFullYear(), "-").concat(target.getMonth());
    var node = nodes.current[key];

    if (node !== null && node !== void 0 && node.el() && scrollBodyRef.current && weekRef.current) {
      var _node$el;

      scrollIntoView.current = true;
      var top = (_node$el = node.el()) === null || _node$el === void 0 ? void 0 : _node$el.offsetTop;

      var _getElementSize = getElementSize(weekRef.current),
          height = _getElementSize.height;

      scrollBodyRef.current.scrollTop = top - height;
    }
  };

  var handleDateClick = useCallback(function (date) {
    var step = state.step,
        steps = state.steps;
    var currentStep = step + 1;
    var idx = value.map(Number).indexOf(Number(date));

    if (currentStep === 1 && mode !== 'multiple') {
      value.splice(0, value.length);
    }

    if (mode === 'range') {
      value[currentStep - 1] = date;
    } else if (idx > -1) {
      value.splice(idx, 1);
    } else if (mode === 'multiple') {
      value.push(date);
    } else {
      value[currentStep - 1] = date;
    }

    value.sort(function (item1, item2) {
      return +item1 - +item2;
    });
    setState(function (prevState) {
      return _objectSpread(_objectSpread({}, prevState), {}, {
        value: value,
        step: currentStep === steps ? 0 : currentStep
      });
    });

    if ((currentStep >= steps || mode === 'multiple') && typeof onChange === 'function') {
      onChange(value);
    }
  }, [value, mode, onChange, state]);

  var renderMonth = function renderMonth(dateMonth) {
    var key = "".concat(dateMonth.getFullYear(), "-").concat(dateMonth.getMonth() + 1);
    return /*#__PURE__*/React.createElement(CalendarMonthView, {
      key: key,
      min: min,
      max: max,
      mode: mode,
      value: value,
      dateMonth: dateMonth,
      dateRender: dateRender,
      disabledDate: disabledDate,
      onDateClick: handleDateClick,
      ref: function ref(n) {
        nodes.current[key] = n;
      }
    });
  };

  var content = useMemo(function () {
    return months.map(function (item) {
      return renderMonth(item);
    });
  }, [months, min, max, disabledDate, dateRender, mode, handleDateClick, value]);
  var showHeader = useMemo(function () {
    return direction === 'horizontal' && header;
  }, [direction, header]);
  var weekNode = weekRef === null || weekRef === void 0 ? void 0 : weekRef.current;
  var bodyScroll = throttle(function () {
    var body = scrollBodyRef.current;

    if (!body) {
      return false;
    }

    var _ref = body,
        scrollTop = _ref.scrollTop;
    var keys = Object.keys(nodes === null || nodes === void 0 ? void 0 : nodes.current);
    keys = keys.sort(function (a, b) {
      return new Date(a).getTime() - new Date(b).getTime();
    });

    for (var i = 0; i < keys.length; i++) {
      var _nodes$current$keys$i;

      var el = nodes === null || nodes === void 0 ? void 0 : (_nodes$current$keys$i = nodes.current[keys[i]]) === null || _nodes$current$keys$i === void 0 ? void 0 : _nodes$current$keys$i.el();

      if ((el === null || el === void 0 ? void 0 : el.offsetTop) + (el === null || el === void 0 ? void 0 : el.clientHeight) - (weekNode === null || weekNode === void 0 ? void 0 : weekNode.clientHeight) > scrollTop) {
        setScrollDate(el.getAttribute('title'));
        return;
      }
    }
  }, 150);
  var monthsContent = isHorizontal ? /*#__PURE__*/React.createElement(Carousel, {
    className: bem('body'),
    showPagination: false,
    activeIndex: currentMonth,
    onChange: setCurrentMonth,
    ref: carouselRef
  }, content) : /*#__PURE__*/React.createElement("div", {
    className: bem('body'),
    ref: scrollBodyRef,
    onScroll: bodyScroll
  }, content, /*#__PURE__*/React.createElement(Transition, {
    in: scrolling,
    timeout: 500
  }, function (tState) {
    return /*#__PURE__*/React.createElement("div", {
      className: bem('scroll-month', [_defineProperty({}, tState, true)])
    }, scrollDate);
  }));
  useEffect(function () {
    !isHorizontal && anchor();
  }, [direction, minDate, maxDate]);
  var timer = useRef();
  useScroll({
    container: scrollBodyRef,
    onScroll: function onScroll() {
      !scrollIntoView.current && setScrolling(true);

      if (timer.current) {
        clearTimeout(timer.current);
      }

      timer.current = setTimeout(function () {
        setScrolling(false);
        scrollIntoView.current = false;
      }, 250);
    }
  });
  useEffect(function () {
    setState(_objectSpread(_objectSpread({}, parseState(props)), {}, {
      step: state.step
    }));
  }, [mode, maxDate, minDate, direction]);
  return /*#__PURE__*/React.createElement("div", {
    className: cls,
    ref: container
  }, showHeader && /*#__PURE__*/React.createElement(Header, {
    changeMonth: function changeMonth(idx) {
      var _carouselRef$current;

      // @ts-ignore
      carouselRef === null || carouselRef === void 0 ? void 0 : (_carouselRef$current = carouselRef.current) === null || _carouselRef$current === void 0 ? void 0 : _carouselRef$current.onSlideTo(idx);
    },
    months: months,
    currentMonth: currentMonth
  }), /*#__PURE__*/React.createElement(Week, {
    ref: weekRef
  }), monthsContent);
});
Calendar.defaultProps = {
  mode: 'single',
  dateRender: function dateRender(date) {
    return date.getDate();
  },
  disabledDate: function disabledDate() {
    return false;
  },
  direction: 'vertical',
  header: false
};
export default Calendar;