import React, { useState, useCallback, ReactNodeArray, useEffect, useImperativeHandle } from 'react';
import styled, { css } from 'styled-components';
import { animated, useTransition } from 'react-spring';
import { cssUnitCalc } from 'utils';

type IProps = {
    children: ReactNodeArray;
    width?: number | string;
    height?: number | string;
    /** 是否开启自动播放 */
    autoplay?: boolean;
    clickAble?: boolean;
    /** 自动播放每帧的时间间隔（毫秒） */
    playInterval?: number;
    /** 轮播结束是否从头开始 */
    rewind?: boolean;
    direction?: 'vertical' | 'horizontal';
    /** 悬停在组件上暂停轮播 */
    hoverPause?: boolean;
    Indicator: any;
    /** 提示点的位置 */
    indicatorPosition?: 'top' | 'right' | 'bottom' | 'left';
};

const Wrap = styled.div<any>`
    width: ${p => cssUnitCalc(p.width)};
    height: ${p => cssUnitCalc(p.height)};
    display: inline-block;
    position: relative;
    overflow: hidden;
`;
const ItemWrap = styled.div<any>`
    width: 100%;
    height: 100%;
    position: absolute;
    will-change: transform, opacity;
    display: flex;
    justify-content: center;
    align-items: center;
    > * {
        width: 100%;
        height: 100%;
    }
`;
const AnimatedItemWrap = animated(ItemWrap);

const Transition = function(
    {
        children,
        width,
        height,
        rewind,
        autoplay,
        playInterval,
        Indicator,
        direction,
        hoverPause,
        indicatorPosition,
        clickAble,
        ...rest
    }: IProps,
    ref: any
) {
    const [index, set] = useState(0);
    useImperativeHandle(
        ref,
        () => {
            return { set };
        },
        []
    );
    const [hover, setHover] = useState(false);
    const onClick = useCallback(() => {
        if (hoverPause && hover && !clickAble) {
            return;
        }
        !document.hidden &&
            clickAble &&
            set(state => (rewind ? (state + 1) % children.length : Math.min(state + 1, children.length - 1)));
    }, [hover, hoverPause, rewind, clickAble, document.hidden]);
    useEffect(() => {
        if (autoplay) {
            var handle = setInterval(onClick, playInterval);
        }
        return () => {
            clearInterval(handle);
        };
    }, [index, hover, autoplay]);
    const horizontal = direction === 'horizontal';
    const transitions = useTransition(index, p => p, {
        from: { opacity: 0, transform: `translate3d(${horizontal ? '100%' : '0'},${horizontal ? '0' : '100%'},0)` },
        enter: { opacity: 1, transform: `translate3d(0%,0,0)` },
        leave: { opacity: 0, transform: `translate3d(${horizontal ? '-50%' : '0'},${horizontal ? '0' : '-50%'},0)` },
    });
    return (
        <>
            <Wrap
                onClick={onClick}
                width={width}
                height={height}
                isHorizontal={horizontal}
                {...rest}
                onMouseEnter={() => setHover(true)}
                onMouseLeave={() => setHover(false)}
            >
                {transitions.map(({ item, props, key }: any) => {
                    return (
                        <AnimatedItemWrap key={key} style={props}>
                            {children[item]}
                        </AnimatedItemWrap>
                    );
                })}
            </Wrap>
            <Indicator
                activeIndex={index}
                total={children.length}
                outsideVertical={direction === 'vertical' && indicatorPosition === 'right'}
            />
        </>
    );
};
export default React.forwardRef(Transition);
