import React, { useEffect, useRef, useState, memo } from 'react';
import { Wrapper } from './style';
import { getTextWidth } from 'utils';
import { ILine } from './types';

export const LineEllipsis = function({
    children = '',
    line = 2,
    foldable = false,
    width = 120,
    actionText = ['更多', '收起'],
    ...rest
}: ILine) {
    const ref: any = useRef();
    const [rendered, set] = useState(children);
    const [isOpen, setIsOpen] = useState(false);
    const [showAction, setShowAction] = useState(false);
    useEffect(() => {
        const containerWidth = width - 4;
        // 隐藏状态或者低于单字符宽度，直接退出计算
        if (containerWidth < 17) {
            return;
        }
        // 不换行文本原始长度
        const textOriginWidth = getTextWidth(children, ref.current);
        // 平均每个字符的长度（概数，可能有字母汉字数字混合情况或者非等宽字体）
        const avgCharWidth = textOriginWidth / (children.length || 1);
        // 大概的换行索引
        let likelyReturnIdx = Math.floor(containerWidth / (avgCharWidth || 1));
        // 每行大概的个数
        const rowWidth = likelyReturnIdx;
        // 准确的换行索引
        const returnIdx: number[] = [];

        // 需要加省略号
        const needEllipsis = containerWidth * line < textOriginWidth;
        needEllipsis && setShowAction(needEllipsis);
        if (needEllipsis) {
            let characters = children.split('');
            Array(line)
                .fill(0)
                .forEach((_, idx) => {
                    while (
                        containerWidth >
                        getTextWidth(
                            characters
                                .slice(returnIdx[idx - 1] || 0, likelyReturnIdx)
                                //.concat([idx === line - 1 && foldable ? '...' + actionText[0] : ''])
                                .join(''),
                            ref.current
                        )
                    ) {
                        likelyReturnIdx += 1;
                        if (likelyReturnIdx > characters.length) {
                            break;
                        }
                    }
                    returnIdx.push(likelyReturnIdx - 1);
                    likelyReturnIdx += rowWidth;
                });
            let lastIndex = returnIdx.pop() as number;
            let lastStartIndex = (returnIdx.pop() as number) - 1;
            while (
                containerWidth <
                getTextWidth(
                    characters
                        .slice(lastStartIndex || 0, lastIndex)
                        .concat(['...', foldable ? actionText[0] : ''])
                        .join(''),
                    ref.current
                )
            ) {
                lastIndex -= 1;
                if (lastIndex === 0) {
                    break;
                }
            }
            set(
                characters
                    .slice(0, lastIndex)
                    .concat(['...'])
                    .join('')
            );
        } else {
            set(children);
        }
    }, [children, line]);
    return (
        <Wrapper ref={ref} {...rest} width={width}>
            {((foldable && !isOpen) || !foldable) && rendered}
            {foldable && !isOpen && showAction && (
                <span className="foldable-span" onClick={() => setIsOpen(true)}>
                    {isOpen ? actionText[1] : actionText[0]}
                </span>
            )}
            {foldable && isOpen && (
                <>
                    {children}
                    <span className="foldable-span" style={{ float: 'right' }} onClick={() => setIsOpen(false)}>
                        {isOpen ? actionText[1] : actionText[0]}
                    </span>
                </>
            )}
        </Wrapper>
    );
};
LineEllipsis.defaultProps = {
    width: 120,
    line: 2,
    foldable: false,
};
export default memo(LineEllipsis);
