import _extends from "@babel/runtime/helpers/extends";
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
import React, { cloneElement, Children, forwardRef, useState, useEffect, useRef, useCallback, useMemo, useImperativeHandle } from 'react';
import { createBEM } from '@zarm-design/bem';
import { useDrag } from '@use-gesture/react';
import Events from '../utils/events';
import { ConfigContext } from '../config-provider';
var Carousel = /*#__PURE__*/forwardRef(function (props, ref) {
  var _React$useContext = React.useContext(ConfigContext),
      prefixCls = _React$useContext.prefixCls;

  var bem = createBEM('carousel', {
    prefixCls: prefixCls
  });
  var className = props.className,
      height = props.height,
      style = props.style,
      children = props.children,
      direction = props.direction,
      loop = props.loop,
      onChangeEnd = props.onChangeEnd,
      onChange = props.onChange,
      autoPlay = props.autoPlay,
      autoPlayIntervalTime = props.autoPlayIntervalTime,
      swipeable = props.swipeable,
      animationDuration = props.animationDuration,
      propActiveIndex = props.activeIndex,
      showPagination = props.showPagination,
      moveDistanceRatio = props.moveDistanceRatio,
      moveTimeSpan = props.moveTimeSpan;
  var stateRef = useRef({
    activeIndex: propActiveIndex,
    activeIndexChanged: false
  });

  var _useState = useState(stateRef.current.activeIndex),
      _useState2 = _slicedToArray(_useState, 2),
      activeIndexState = _useState2[0],
      setActiveIndexState = _useState2[1];

  var updateRef = useRef(function (state) {
    stateRef.current = state;
    setActiveIndexState(state.activeIndex);
  });
  var isVertical = direction === 'vertical';
  var carouselRef = ref || /*#__PURE__*/React.createRef();
  var carouselItemsRef = useRef(null);
  var translateXRef = useRef(0);
  var translateYRef = useRef(0);
  var count = useMemo(function () {
    return Children.count(children);
  }, [children]); // 处理节点（首尾拼接）

  var carouselItems = useMemo(function () {
    if (children == null || children.length === 0) {
      return;
    } // 增加头尾拼接节点


    var itemList = _toConsumableArray(children);

    var firstItem = itemList[0];
    var lastItem = itemList[itemList.length - 1];

    if (loop) {
      itemList.push(firstItem);
      itemList.unshift(lastItem);
    } // 节点追加后重排key


    var newItems = React.Children.map(itemList, function (element, index) {
      return /*#__PURE__*/cloneElement(element, {
        key: index,
        className: bem('item', [element.props.className])
      });
    });
    return newItems;
  }, [children]); // 执行过渡动画

  var doTransition = useCallback(function (offset, animationDurationNum) {
    var dom = carouselItemsRef.current;
    var x = 0;
    var y = 0;

    if (!isVertical) {
      x = offset.x;
    } else {
      y = offset.y;
    }

    dom.style.transitionDuration = "".concat(animationDurationNum, "ms");
    dom.style.transform = "translate3d(".concat(x, "px, ").concat(y, "px, 0)");
  }, [isVertical]);
  var onMoving = useRef(false);
  var transitionEnd = useCallback(function () {
    onMoving.current = false;
    var _stateRef$current = stateRef.current,
        activeIndex = _stateRef$current.activeIndex,
        activeIndexChanged = _stateRef$current.activeIndexChanged;
    var dom = carouselItemsRef.current;
    var index = loop ? activeIndex + 1 : activeIndex;
    translateXRef.current = -dom.offsetWidth * index;
    translateYRef.current = -dom.offsetHeight * index;
    doTransition({
      x: translateXRef.current,
      y: translateYRef.current
    }, 0);

    if (activeIndexChanged) {
      onChangeEnd === null || onChangeEnd === void 0 ? void 0 : onChangeEnd(activeIndex);
    }
  }, [loop, doTransition, onChangeEnd]); // 移动到指定编号

  var onMoveTo = useCallback(function (index, animationDurationNum) {
    var dom = carouselItemsRef.current;
    var previousIndex = stateRef.current.activeIndex;
    var activeIndexChanged = previousIndex !== index;
    var num = loop ? 1 : 0;
    translateXRef.current = -dom.offsetWidth * (index + num);
    translateYRef.current = -dom.offsetHeight * (index + num);
    doTransition({
      x: translateXRef.current,
      y: translateYRef.current
    }, animationDurationNum);

    if (index > count - 1) {
      index = 0;
    } else if (index < 0) {
      index = count - 1;
    }

    updateRef.current({
      activeIndex: index,
      activeIndexChanged: activeIndexChanged
    });

    if (activeIndexChanged) {
      onChange === null || onChange === void 0 ? void 0 : onChange(index);
    }
  }, [children, doTransition, loop, onChange]); // 滑动到指定编号

  var _onSlideTo = useCallback(function (index) {
    onMoveTo(index, animationDuration);
  }, [onMoveTo, animationDuration]); // 静默跳到指定编号


  var _onJumpTo = useCallback(function (index) {
    onMoveTo(index, 0);
  }, [onMoveTo]); // 更新窗口变化的位置偏移


  var resize = useCallback(function () {
    _onJumpTo(stateRef.current.activeIndex);
  }, [_onJumpTo]);
  var intervalRef = useRef();
  var bind = useDrag(function (state) {
    var activeIndex = stateRef.current.activeIndex;

    if (onMoving.current) {
      if (activeIndex <= 0) {
        _onJumpTo(0);
      } else if (activeIndex >= count - 1) {
        _onJumpTo(count - 1);
      }

      onMoving.current = false;
    }

    if (!state.intentional) {
      return false;
    }

    ;
    intervalRef.current && window.clearInterval(intervalRef.current);
    var offset = state.offset,
        elapsedTime = state.elapsedTime;

    var _offset = _slicedToArray(offset, 2),
        offsetX = _offset[0],
        offsetY = _offset[1];

    var index = isVertical ? 1 : 0;

    if (!offset[index]) {
      return false;
    }

    var action = !isVertical && offsetX > 0 || isVertical && offsetY > 0 ? 'prev' : 'next';

    if (!loop && (action === 'prev' && activeIndex <= 0 || action === 'next' && activeIndex >= count - 1)) {
      return false;
    }

    if (state.last) {
      var dom = carouselItemsRef.current;
      var ratio = !isVertical ? Math.abs(offsetX / dom.offsetWidth) : Math.abs(offsetY / dom.offsetHeight); // 判断滑动临界点
      // 1.滑动距离超过0，且滑动距离和父容器长度之比超过moveDistanceRatio
      // 2.滑动释放时间差低于moveTimeSpan

      if (ratio >= moveDistanceRatio || elapsedTime <= moveTimeSpan) {
        activeIndex = action === 'next' ? activeIndex + 1 : activeIndex - 1;
      }

      if (loop && (activeIndex >= count - 1 || activeIndex <= 1)) {
        onMoving.current = true;
      }

      _onSlideTo(activeIndex);

      return false;
    }

    doTransition({
      x: translateXRef.current + offset[0],
      y: translateYRef.current + offset[1]
    }, 0);
  }, {
    from: function from() {
      return [0, 0];
    },
    enabled: swipeable,
    axis: isVertical ? 'y' : 'x',
    pointer: {
      touch: true
    },
    preventScroll: !isVertical,
    triggerAllEvents: true
  });
  useEffect(function () {
    if (!autoPlay || count <= 1) return;
    intervalRef.current = window.setInterval(function () {
      !onMoving.current && _onSlideTo(stateRef.current.activeIndex + 1);
    }, autoPlayIntervalTime);
    return function () {
      window.clearInterval(intervalRef.current);
    };
  }, [autoPlay, autoPlayIntervalTime, loop, _onSlideTo, stateRef.current.activeIndex]);
  useEffect(function () {
    // 监听窗口变化
    Events.on(window, 'resize', resize); // 设置起始位置编号

    _onJumpTo(propActiveIndex);

    return function () {
      // 移除监听窗口变化
      Events.off(window, 'resize', resize);
    };
  }, [_onJumpTo, _onSlideTo, propActiveIndex, resize, transitionEnd]);
  useImperativeHandle(carouselRef, function () {
    return {
      onJumpTo: function onJumpTo(index) {
        _onJumpTo(index);
      },
      onSlideTo: function onSlideTo(index) {
        _onSlideTo(index);
      }
    };
  });
  var pagination = useMemo(function () {
    if (!showPagination) return null;
    var paginationItems = Children.map(children, function (_child, index) {
      return /*#__PURE__*/React.createElement("div", {
        key: "pagination-".concat(+index),
        className: bem('pagination__item', [{
          active: index === activeIndexState
        }]),
        onClick: function onClick() {
          return _onSlideTo(index);
        }
      });
    });
    return /*#__PURE__*/React.createElement("div", {
      className: bem('pagination')
    }, paginationItems);
  }, [showPagination, children, activeIndexState]);
  var cls = bem([{
    horizontal: !isVertical,
    vertical: isVertical
  }, className]);
  var itemsStyle = {};

  if (isVertical) {
    itemsStyle.height = height;
  }

  return /*#__PURE__*/React.createElement("div", _extends({
    className: cls,
    style: style,
    ref: carouselRef
  }, bind()), /*#__PURE__*/React.createElement("div", {
    ref: carouselItemsRef,
    className: bem('items'),
    onTransitionEnd: transitionEnd,
    style: itemsStyle
  }, carouselItems), pagination);
});
Carousel.displayName = 'Carousel';
Carousel.defaultProps = {
  direction: 'horizontal',
  height: 160,
  loop: false,
  activeIndex: 0,
  animationDuration: 500,
  swipeable: true,
  autoPlay: false,
  autoPlayIntervalTime: 3000,
  moveDistanceRatio: 0.5,
  moveTimeSpan: 300,
  showPagination: true
};
export default Carousel;