import { clsName } from "../util";
import { COMPS_NAME, HOOKS_NAME } from "../util/constant";
import { isNumber } from "../../../src/utils/index.js";

export default {
    name: COMPS_NAME.VE_TABLE_COLUMN_RESISZER,
    props: {
        parentRendered: {
            type: Boolean,
            required: true,
        },
        tableContainerEl: {
            type: HTMLDivElement,
            default: null,
        },
        hooks: {
            type: Object,
            required: true,
        },
        colgroups: {
            type: Array,
            required: true,
        },
        isColumnResizerHover: {
            type: Boolean,
            required: true,
        },
        isColumnResizing: {
            type: Boolean,
            required: true,
        },
        setIsColumnResizerHover: {
            type: Function,
            required: true,
        },
        setIsColumnResizing: {
            type: Function,
            required: true,
        },
        setColumnWidth: {
            type: Function,
            required: true,
        },
        // column width resize option
        columnWidthResizeOption: {
            type: Object,
            default: function () {
                return null;
            },
        },
    },
    data() {
        return {
            // column resizer start x
            columnResizerStartX: 0,
            // current resizing column
            currentResizingColumn: null,
            // column resizer handler width
            columnResizerHandlerWidth: 5,
            // column resizer rect
            columnResizerRect: {
                top: 0,
                left: 0,
                height: 0,
            },
        };
    },
    computed: {
        // column min width
        columnMinWidth() {
            let result = 30;

            const { columnWidthResizeOption } = this;

            if (columnWidthResizeOption) {
                const { minWidth } = columnWidthResizeOption;
                if (isNumber(minWidth) && minWidth > 0) {
                    result = minWidth;
                }
            }
            return result;
        },
    },
    watch: {
        parentRendered: {
            handler: function (val) {
                if (val) {
                    // header cell mousemove
                    this.hooks.addHook(
                        HOOKS_NAME.HEADER_CELL_MOUSEMOVE,
                        ({ event, column }) => {
                            if (column.disableResizing) return;
                            this.initColumnResizerPosition({ event, column });
                        },
                    );
                }
            },
            immediate: true,
        },
    },
    methods: {
        // init column resizer position
        initColumnResizerPosition({ event, column }) {
            const { tableContainerEl, isColumnResizing } = this;

            if (tableContainerEl && !isColumnResizing) {
                const { left: tableContainerLeft, top: tableContainerTop } =
                    tableContainerEl.getBoundingClientRect();

                const col = this.colgroups.find((x) => x.key === column.key);

                // 表头分组，不支持分组表头列宽拖动
                if (!col) {
                    return false;
                }

                if (col._realTimeWidth) {
                    const target = event.target;
                    const cellRect = target.getBoundingClientRect();
                    const { height, left, top } = cellRect;

                    this.columnResizerRect.left =
                        left + col._realTimeWidth - tableContainerLeft;
                    this.columnResizerRect.top = top - tableContainerTop;
                    this.columnResizerRect.height = height;

                    this.currentResizingColumn = col;
                    this.columnResizerStartX = left + col._realTimeWidth;
                } else {
                    console.warn("Resizer column needs set column width");
                }
            }
        },

        // set column resizer position byu drag
        setColumnResizerPositionByDrag(event) {
            const {
                tableContainerEl,
                isColumnResizing,
                currentResizingColumn,
            } = this;

            if (tableContainerEl && isColumnResizing) {
                const { left: tableContainerLeft } =
                    tableContainerEl.getBoundingClientRect();

                if (isColumnResizing && currentResizingColumn) {
                    const { columnResizerStartX, columnMinWidth } = this;

                    // 不允许拖动小于列最小宽度
                    if (
                        currentResizingColumn._realTimeWidth +
                            (event.clientX - columnResizerStartX) >
                        columnMinWidth
                    ) {
                        this.columnResizerRect.left =
                            event.clientX - tableContainerLeft;
                    }
                }
            }
        },

        // column resizer handler mousedown
        columnResizerHandlerMousedown({ event }) {
            if (this.isColumnResizerHover) {
                this.setIsColumnResizing(true);

                // add document mousemove listener
                document.addEventListener(
                    "mousemove",
                    this.setColumnResizerPositionByDrag,
                );
                // add document mouseup listener
                document.addEventListener("mouseup", this.columnResizerMouseup);

                // stop text select when reszing
                document.onselectstart = function () {
                    return false;
                };
                document.ondragstart = function () {
                    return false;
                };
            }
        },

        // column resizer mouseup
        columnResizerMouseup(event) {
            const {
                isColumnResizing,
                currentResizingColumn,
                columnResizerStartX,
                setColumnWidth,
                columnWidthResizeOption,
                columnMinWidth,
            } = this;

            if (!isColumnResizing || !currentResizingColumn) {
                return false;
            }

            let differWidth;
            // 拖动小于列最小宽度
            if (
                currentResizingColumn._realTimeWidth +
                    (event.clientX - columnResizerStartX) <
                columnMinWidth
            ) {
                differWidth =
                    columnMinWidth - currentResizingColumn._realTimeWidth;
            } else {
                differWidth = event.clientX - columnResizerStartX;
            }
            differWidth = Math.floor(differWidth);

            // 偏差阈值，低于则不处理
            if (Math.abs(differWidth) > 1) {
                let nextColumnWidth = currentResizingColumn._realTimeWidth;
                nextColumnWidth += differWidth;

                // set column width
                setColumnWidth({
                    colKey: currentResizingColumn.key,
                    width: nextColumnWidth,
                });

                if (columnWidthResizeOption) {
                    const { sizeChange } = columnWidthResizeOption;
                    sizeChange &&
                        sizeChange({
                            column: currentResizingColumn,
                            differWidth,
                            columnWidth: nextColumnWidth,
                        });
                }
            }

            this.clearColumnResizerStatus();
            // add document mousemove listener
            document.removeEventListener(
                "mousemove",
                this.setColumnResizerPositionByDrag,
            );
            // add document mouseup listener
            document.removeEventListener("mouseup", this.columnResizerMouseup);
        },

        // clear column resizer status
        clearColumnResizerStatus() {
            this.currentResizingColumn = null;
            this.columnResizerStartX = 0;
            this.setIsColumnResizerHover(false);
            this.setIsColumnResizing(false);

            // enable text select when reszing
            document.onselectstart = function () {
                return true;
            };
            document.ondragstart = function () {
                return true;
            };
        },
    },

    render() {
        const {
            isColumnResizerHover,
            isColumnResizing,
            columnResizerRect,
            columnResizerHandlerWidth,
        } = this;

        const { left, top, height } = columnResizerRect;

        const columnResizerHandlerProps = {
            class: {
                [clsName("column-resizer-handler")]: true,
                ["active"]: isColumnResizerHover || isColumnResizing,
            },
            style: {
                left: left - columnResizerHandlerWidth + "px",
                top: top + "px",
                height: height + "px",
            },
            on: {
                click: () => {
                    //
                },
                mousedown: (event) => {
                    this.columnResizerHandlerMousedown({ event });
                },
                mouseenter: () => {
                    this.setIsColumnResizerHover(true);
                },
                mouseleave: () => {
                    this.setIsColumnResizerHover(false);
                },
                mouseup: (event) => {
                    this.columnResizerMouseup(event);
                },
            },
        };

        const columnResizerLineProps = {
            class: [clsName("column-resizer-line")],
            style: {
                display: isColumnResizing ? "block" : "none",
                left: left + "px",
            },
        };

        return (
            <div class={clsName("column-resizer")}>
                <div {...columnResizerHandlerProps} />
                <div {...columnResizerLineProps} />
            </div>
        );
    },
};
