"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useScroll = void 0;
const seemly_1 = require("seemly");
const vue_1 = require("vue");
const _utils_1 = require("../../_utils");
const utils_1 = require("./utils");
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
function useScroll(props, { mainTableInstRef, mergedCurrentPageRef, bodyWidthRef, scrollPartRef }) {
    let scrollLeft = 0;
    const leftActiveFixedColKeyRef = vue_1.ref(null);
    const rightActiveFixedColKeyRef = vue_1.ref(null);
    const styleScrollXRef = vue_1.computed(() => {
        return _utils_1.formatLength(props.scrollX);
    });
    const leftFixedColumnsRef = vue_1.computed(() => {
        return props.columns.filter((column) => column.fixed === 'left');
    });
    const rightFixedColumnsRef = vue_1.computed(() => {
        return props.columns.filter((column) => column.fixed === 'right');
    });
    const fixedColumnLeftMapRef = vue_1.computed(() => {
        const columns = {};
        let left = 0;
        for (const column of leftFixedColumnsRef.value) {
            columns[utils_1.getColKey(column)] = left;
            left += utils_1.getColWidth(column) || 0;
        }
        return columns;
    });
    const fixedColumnRightMapRef = vue_1.computed(() => {
        const columns = {};
        let right = 0;
        for (const column of rightFixedColumnsRef.value.reverse()) {
            columns[utils_1.getColKey(column)] = right;
            right += column.width || 0;
        }
        return columns;
    });
    function deriveActiveLeftFixedColumn() {
        // target is header element
        const { value: leftFixedColumns } = leftFixedColumnsRef;
        let leftWidth = 0;
        const { value: fixedColumnLeftMap } = fixedColumnLeftMapRef;
        let leftActiveFixedColKey = null;
        for (let i = 0; i < leftFixedColumns.length; ++i) {
            const key = utils_1.getColKey(leftFixedColumns[i]);
            if (scrollLeft > (fixedColumnLeftMap[key] || 0) - leftWidth) {
                leftActiveFixedColKey = key;
                leftWidth += utils_1.getColWidth(leftFixedColumns[i]) || 0;
            }
            else {
                break;
            }
        }
        leftActiveFixedColKeyRef.value = leftActiveFixedColKey;
    }
    function deriveActiveRightFixedColumn() {
        // target is header element
        const { value: rightFixedColumns } = rightFixedColumnsRef;
        const scrollWidth = Number(props.scrollX);
        const { value: tableWidth } = bodyWidthRef;
        if (tableWidth === null)
            return;
        let rightWidth = 0;
        let rightActiveFixedColKey = null;
        const { value: fixedColumnRightMap } = fixedColumnRightMapRef;
        for (let i = 0; i < rightFixedColumns.length; ++i) {
            const key = utils_1.getColKey(rightFixedColumns[i]);
            if (Math.round(scrollLeft + (fixedColumnRightMap[key] || 0) + tableWidth - rightWidth) < scrollWidth) {
                rightActiveFixedColKey = key;
                rightWidth += utils_1.getColWidth(rightFixedColumns[i]) || 0;
            }
            else {
                break;
            }
        }
        rightActiveFixedColKeyRef.value = rightActiveFixedColKey;
    }
    function getScrollElements() {
        const header = mainTableInstRef.value
            ? mainTableInstRef.value.getHeaderElement()
            : null;
        const body = mainTableInstRef.value
            ? mainTableInstRef.value.getBodyElement()
            : null;
        return {
            header,
            body
        };
    }
    function scrollMainTableBodyToTop() {
        const { body } = getScrollElements();
        if (body) {
            body.scrollTop = 0;
        }
    }
    function handleTableHeaderScroll() {
        if (scrollPartRef.value === 'head') {
            seemly_1.beforeNextFrameOnce(syncScrollState);
        }
    }
    function handleTableBodyScroll() {
        if (scrollPartRef.value === 'body') {
            seemly_1.beforeNextFrameOnce(syncScrollState);
        }
    }
    function syncScrollState() {
        // We can't simply use props.scrollX to determine whether the table has
        // need to be sync since user may set column width for each column.
        // Just let it be, the scroll listener won't be triggered for a basic table.
        const { header, body } = getScrollElements();
        if (!body)
            return;
        const { value: tableWidth } = bodyWidthRef;
        if (tableWidth === null)
            return;
        const { value: scrollPart } = scrollPartRef;
        if (props.maxHeight || props.flexHeight) {
            if (!header)
                return;
            // we need to deal with overscroll
            if (scrollPart === 'head') {
                scrollLeft = header.scrollLeft;
                body.scrollLeft = scrollLeft;
            }
            else {
                scrollLeft = body.scrollLeft;
                header.scrollLeft = scrollLeft;
            }
        }
        else {
            scrollLeft = body.scrollLeft;
        }
        deriveActiveLeftFixedColumn();
        deriveActiveRightFixedColumn();
    }
    function setHeaderScrollLeft(left) {
        const { header } = getScrollElements();
        if (!header)
            return;
        header.scrollLeft = left;
        syncScrollState();
    }
    vue_1.watch(mergedCurrentPageRef, () => {
        scrollMainTableBodyToTop();
    });
    return {
        styleScrollXRef,
        fixedColumnLeftMapRef,
        fixedColumnRightMapRef,
        leftFixedColumnsRef,
        rightFixedColumnsRef,
        leftActiveFixedColKeyRef,
        rightActiveFixedColKeyRef,
        syncScrollState,
        handleTableBodyScroll,
        handleTableHeaderScroll,
        setHeaderScrollLeft
    };
}
exports.useScroll = useScroll;
