import * as React from 'react';
import { useState, useEffect, useRef, useCallback } from 'react';
import * as propTypes from 'prop-types';
import classNames from '../../utils/classnames';
import Swipe from 'react-easy-swipe';

import './index.css';

export default function Swiper({
  children,
  className,
  style = {},
  autoplay,
  circular,
  vertical,
  indicatorDots,
  indicatorColor,
  indicatorActiveColor,
  duration = 500,
  interval = 5000,
  current = 0,
  events = {},
  id,
}) {
  const itemCount = React.Children.count(children);
  current = Math.max(0, Math.min(itemCount - 1, current));

  const [currentIndex, setCurrentIndex] = useState(current);
  const [swipeStyle, setSwipeStyle] = useState(null);
  const [height, setHeight] = useState(0);

  const { change = () => {} } = events;

  // 自动切换
  useEffect(() => {
    if (autoplay) {
      const timer = setInterval(() => {
        setIndex(currentIndex + 1);
      }, interval);

      return () => clearInterval(timer);
    }
  }, [currentIndex, autoplay]);

  // 触发切换
  const pre = useRef({ index: currentIndex }).current;
  useEffect(() => {
    updateSwipeStyle(currentIndex, pre.index, itemCount);

    change({
      current: currentIndex,
    });
    return () => {
      pre.index = currentIndex;
    };
  }, [currentIndex, vertical]);

  const cb = useCallback(
    (node) => {
      if (node) {
        const h =
          node.children[0] &&
          node.children[0].getBoundingClientRect() &&
          node.children[0].getBoundingClientRect().height;

        if (h && height) {
          setHeight(Math.min(h, height));
        } else {
          setHeight(Math.max(h, height));
        }
      }
    },
    [height]
  );

  const itemsClone = React.Children.map(children, (x, i) => {
    return (
      <div className="g-swiper-item" data-index={i}>
        {x}
      </div>
    );
  });

  const setIndex = (index) => {
    if (index >= itemCount) {
      index = 0;
    }
    if (index < 0) {
      index = itemCount - 1;
    }
    setCurrentIndex(index);
  };

  // 设置容器样式、动画
  // TODO fix settimeout mess
  const updateSwipeStyle = (to, cur, length) => {
    let style;
    // 最后向前到最开始
    if (to === 0 && cur === length - 1) {
      circular &&
        setSwipeStyle({
          transform: `translate3d(0, 0, 0)`,
        });
      setTimeout(() => {
        setSwipeStyle({
          transform: vertical
            ? `translate3d(0, -100%, 0)`
            : `translate3d(-100%, 0, 0)`,
          transitionDuration: `${duration}ms`,
        });
      }, 50);
      return;
    }

    // 第一个后退到最后
    if (to === length - 1 && cur === 0) {
      circular &&
        setSwipeStyle({
          transform: vertical
            ? `translate3d(0, -${(to + 2) * 100}%, 0)`
            : `translate3d(-${(to + 2) * 100}%, 0, 0)`,
        });
      setTimeout(() => {
        setSwipeStyle({
          transform: vertical
            ? `translate3d(0, -${(to + 1) * 100}%, 0)`
            : `translate3d(-${(to + 1) * 100}%, 0, 0)`,
          transitionDuration: `${duration}ms`,
        });
      }, 50);
      return;
    }

    style = {
      transform: vertical
        ? `translate3d(0, -${(to + 1) * 100}%, 0)`
        : `translate3d(-${(to + 1) * 100}%, 0, 0)`,
    };
    if (to !== cur) {
      style.transitionDuration = `${duration}ms`;
    }
    setSwipeStyle(style);
  };

  return (
    <div
      className={classNames('g-swiper weda-ui', className, {
        vertical: vertical,
      })}
      style={{ height: height ? height : 'auto', ...style }}
      onLoad={(e) => {
        cb(e.target.closest('.g-swiper-item'));
      }}
      id={id}
    >
      {itemCount > 0 ? (
        <Swipe
          className="g-swiper-list"
          style={swipeStyle}
          tolerance={20}
          onSwipeLeft={() => {
            vertical || setIndex(currentIndex + 1);
          }}
          onSwipeRight={() => {
            vertical || setIndex(currentIndex - 1);
          }}
          onSwipeDown={() => {
            vertical && setIndex(currentIndex - 1);
          }}
          onSwipeUp={() => {
            vertical && setIndex(currentIndex + 1);
          }}
        >
          {itemsClone[itemCount - 1]}
          {React.Children.map(children, (x, i) => {
            return (
              <div
                className={classNames('g-swiper-item', {
                  current: i === currentIndex,
                })}
                ref={cb}
                data-index={i}
              >
                {x}
              </div>
            );
          })}
          {itemsClone[0]}
        </Swipe>
      ) : null}

      {indicatorDots ? (
        <div className="g-swiper__pagination">
          {React.Children.map(children, (x, i) => {
            return (
              <a
                href="#"
                className="g-swiper__pagination-bulletm"
                style={{
                  backgroundColor:
                    currentIndex === i ? indicatorActiveColor : indicatorColor,
                }}
                onClick={(e) => {
                  setIndex(i);
                  e.preventDefault();
                }}
                data-index={i}
              ></a>
            );
          })}
        </div>
      ) : (
        false
      )}
      <a
        href="javascript:;"
        className="g-swiper__turn-pre"
        onClick={() => {
          setIndex(currentIndex - 1);
        }}
      >
        上一页
      </a>
      <a
        href="javascript:;"
        className="g-swiper__turn-next"
        onClick={() => {
          setIndex(currentIndex + 1);
        }}
      >
        下一页
      </a>
    </div>
  );
}

Swiper.defaultProps = {
  current: 0,
  duration: 500,
  indicatorDots: true,
  autoplay: true,
  circular: true,
  interval: 5000,
  vertical: false,
  indicatorColor: 'rgba(200, 200, 200, 0.9)',
  indicatorActiveColor: 'rgba(0, 0, 0, 0.9)',
};

Swiper.propTypes = {
  /**
   * 是否启用指示点
   */
  indicatorDots: propTypes.bool,
  /**
   * 是否自动切换
   */
  autoplay: propTypes.bool,
  /**
   * 当前索引值
   */
  current: propTypes.number,
  interval: propTypes.number,
  duration: propTypes.number,
  circular: propTypes.bool,
  vertical: propTypes.bool,
  indicatorColor: propTypes.string,
  indicatorActiveColor: propTypes.string,
  children: propTypes.any,
  className: propTypes.string,
  style: propTypes.object,
  events: propTypes.objectOf(propTypes.func),
  id: propTypes.string,
};
