import React, { useCallback, useRef } from 'react';
import classNames from 'classnames';
import s from './DragSorted.less';
import { getCache, saveCache } from '../utils/cache';

const DragSorted = (props: any) => {
    const {
        columnName,
        orderNo,
        onDragSortedCb,
        onDragSortedMove,
        tableId,
        canSorted,
        onDragSorted,
        columns,
        cachedFeAttr,
        position,
        columnChsName,
    } = props;
    if (!canSorted || position === 'left' || position === 'right') {
        return <div className={s.sortedWrap}>{props.children}</div>;
    }
    // 长按计时器
    const timer: any = useRef(null);
    // 表格滚动计时器
    const timerInterval: any = useRef(null);
    // 表格
    const container: any = document.querySelector(`#apolloTable_${tableId}`);
    // 拖拽列时的影子div
    const columnCopyDiv: any = document.querySelector('#columnCopyDiv');
    // 分割线wrap
    const dividerWrap: any = document.querySelector(`#dividerWrap_${tableId}`);
    // 分割线
    const divider: any = document.querySelector(`#divider_${tableId}`);
    // 左侧固定列分割线
    const leftFixedHandleWrap: any = document.querySelector('#leftFixedHandleWrap');
    const rightFixedHandleWrap: any = document.querySelector('#rightFixedHandleWrap');
    // 监听鼠标移动
    const onMouseMove = useCallback((e) => {
        const tableRect = container.getBoundingClientRect();
        const detaX = columnCopyDiv.getAttribute('data-deta-x');
        // 所有列
        const draggableColumns = document.querySelectorAll('.draggableColumn');
        const leftFixedHandleWrapRectX = (leftFixedHandleWrap && leftFixedHandleWrap.getBoundingClientRect().x) || 0;
        const rightFixedHandleWrapRectX =
            (rightFixedHandleWrap && rightFixedHandleWrap.getBoundingClientRect().x) || tableRect.right;

        const columnCopyDivRect = columnCopyDiv.getBoundingClientRect();
        const columnCopyDivWidth = columnCopyDivRect.width;
        const columnCopyDivX = columnCopyDivRect.x;
        // 影子div中间点的x坐标
        const columnCopyDivMid = columnCopyDivX + columnCopyDivWidth / 2;
        const left = e.clientX - tableRect.x - Number(detaX);
        // 影子div随鼠标移动
        // 鼠标在左侧固定列与右侧固定列之间有效
        if (e.clientX > leftFixedHandleWrapRectX && e.clientX < rightFixedHandleWrapRectX) {
            columnCopyDiv.style.left = `${left}px`;
        }
        draggableColumns.forEach((dom) => {
            const domRect = dom.getBoundingClientRect();
            // 当前节点在左侧固定列与右侧固定列之间有效
            if (
                domRect.x > leftFixedHandleWrapRectX &&
                domRect.x < rightFixedHandleWrapRectX &&
                columnCopyDivMid > domRect.x &&
                columnCopyDivMid < domRect.x + domRect.width
            ) {
                // 影子div中点在投放目标中
                divider.style.left = `${domRect.x - tableRect.x}px`;
                // 收集投放目标的信息
                const dropColumn = dom.getAttribute('data-column-name') || '';
                const dropColumnOrder = dom.getAttribute('data-column-order') || '';
                divider.setAttribute('data-drop-column', dropColumn);
                divider.setAttribute('data-drop-order', dropColumnOrder);
            }
        });

        if (typeof onDragSortedMove === 'function') {
            let dir = '';
            let step = 10;
            // 设置鼠标超出表格左右固定列两侧时的滚动事件
            if (columnCopyDivX + columnCopyDivWidth > rightFixedHandleWrapRectX - 50) {
                dir = 'right';
                step = 100;
            } else if (columnCopyDivX + columnCopyDivWidth > rightFixedHandleWrapRectX - 100) {
                dir = 'right';
                step = 30;
            } else if (columnCopyDivX < leftFixedHandleWrapRectX + 100) {
                dir = 'left';
                step = 30;
            } else if (columnCopyDivX < leftFixedHandleWrapRectX + 50) {
                dir = 'left';
                step = 100;
            } else {
                dir = '';
            }
            if (dir) {
                // 需要滚动，如果已有计时器，先清除再重新设置计时器
                if (timerInterval.current) {
                    clearInterval(timerInterval.current);
                }
                timerInterval.current = setInterval(() => {
                    onDragSortedMove(dir, step);
                }, 150);
            } else {
                // 需要停止，清除已有计时器
                // eslint-disable-next-line no-lonely-if
                if (timerInterval.current) {
                    clearInterval(timerInterval.current);
                    timerInterval.current = null;
                }
            }
        }
    }, []);
    // 监听鼠标抬起
    const onMouseUp = useCallback(() => {
        // 清空计时器
        if (timer.current) {
            clearTimeout(timer.current);
            timer.current = null;
        }
        if (timerInterval.current) {
            clearInterval(timerInterval.current);
            timerInterval.current = null;
        }
        // 移除全局事件
        document.body.removeEventListener('mousemove', onMouseMove, false);
        document.body.removeEventListener('mouseup', onMouseUp, false);
        // 停止拖动时隐藏影子div
        columnCopyDiv.style.display = 'none';
        dividerWrap.style.display = 'none';
        // 获取分割线上挂载的拖动列和投放列信息
        const dragColumn = divider.getAttribute('data-drag-column');
        const dragColumnOrder = divider.getAttribute('data-drag-order');
        const dropColumn = divider.getAttribute('data-drop-column');
        const dropColumnOrder = divider.getAttribute('data-drop-order');
        // 没有列信息
        if (!dragColumn || !dropColumn) {
            return;
        }
        // 没有拖动
        if (Number(dropColumnOrder) === Number(dragColumnOrder)) {
            return;
        }
        // 拖动没有产生移动
        if (Number(dropColumnOrder) - Number(dragColumnOrder) === 1) {
            return;
        }
        // 拖动回调
        const newColumns: any[] = [];
        // 从右往左拖
        if (Number(dragColumnOrder) > Number(dropColumnOrder)) {
            // columns已排序
            columns.map((item: any, i: number) => {
                if (item.orderNo >= Number(dropColumnOrder) && item.orderNo <= Number(dragColumnOrder)) {
                    if (item.columnName === dragColumn) {
                        newColumns.push({
                            ...item,
                            orderNo: Number(dropColumnOrder),
                        });
                    } else {
                        newColumns.push({
                            ...item,
                            orderNo: columns[i + 1].orderNo,
                        });
                    }
                } else {
                    newColumns.push(item);
                }
            });
        } else {
            // 从左往右拖
            const index = columns.findIndex((item: any) => {
                return item.columnName === dropColumn;
            });
            columns.map((item: any, i: number) => {
                if (item.columnName === dragColumn) {
                    newColumns.push({
                        ...item,
                        orderNo: columns[index - 1].orderNo,
                    });
                } else if (item.orderNo > Number(dragColumnOrder) && item.orderNo < Number(dropColumnOrder)) {
                    newColumns.push({
                        ...item,
                        orderNo: columns[i - 1].orderNo,
                    });
                } else {
                    newColumns.push(item);
                }
            });
        }
        if (cachedFeAttr) {
            const cachedCols = getCache({ tableId });
            if (cachedCols) {
                newColumns.map((item: any) => {
                    cachedCols[item.columnName] = {
                        ...cachedCols[item.columnName],
                        orderNo: item.orderNo,
                    };
                });
                saveCache({ tableId, data: cachedCols });
            }
        }
        if (typeof onDragSorted === 'function') {
            onDragSorted(newColumns);
        }
        // if (typeof onDragSortedCb === 'function') {
        //     onDragSortedCb(newColumns);
        // }
    }, [onDragSortedCb, onDragSorted, columns]);
    // 监听鼠标按下
    const onMouseDown = useCallback(
        (e) => {
            // 不是左键点击不作处理
            if (e.button !== 0) {
                return;
            }
            // 表格初始位置x点
            const originLeft = container.getBoundingClientRect().x || 0;
            // 拖动列矩形
            const targetRect = e.currentTarget.getBoundingClientRect();
            const curX = e.clientX;
            // 500ms长按事件，表示想要拖拽
            timer.current = setTimeout(() => {
                // 影子div显示
                columnCopyDiv.style.display = 'block';
                // 影子div初始x位置=拖动列x点-表格x点
                columnCopyDiv.style.left = `${targetRect.x - originLeft}px`;
                // 影子div宽度=拖动列宽度
                columnCopyDiv.style.width = `${targetRect.width}px`;
                columnCopyDiv.innerText = columnChsName;
                // 鼠标x点与拖动列x点之间的距离（记录下来方便后续使用）
                const detaX = curX - targetRect.x;
                columnCopyDiv.setAttribute('data-deta-x', String(detaX));
                // 分割线初始位置为当前列
                divider.style.left = `${targetRect.x - originLeft}px`;
                dividerWrap.style.display = 'block';
                // 给分割线设置拖动列信息，移除投放列信息
                divider.setAttribute('data-drag-column', columnName);
                divider.setAttribute('data-drag-order', orderNo);
                divider.removeAttribute('data-drop-column');
                divider.removeAttribute('data-drop-order');
                // 全局添加监听鼠标移动和松开事件
                document.body.addEventListener('mousemove', onMouseMove, false);
                document.body.addEventListener('mouseup', onMouseUp, false);
            }, 500);
            // 阻止默认行为
            e.preventDefault();
        },
        [columnName, orderNo, onMouseMove, onMouseUp],
    );

    return (
        <div
            className={classNames('draggableColumn', s.sortedWrap, s.sortedAble)}
            onMouseDown={onMouseDown}
            onMouseUp={onMouseUp}
            data-column-name={columnName}
            data-column-order={orderNo}
        >
            {props.children}
        </div>
    );
};
export default DragSorted;
