"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ColumnSizing = exports.defaultColumnSizing = void 0;
exports.passiveEventSupported = passiveEventSupported;
/* eslint-disable import/no-cycle */
const __1 = require("..");
const utils_1 = require("../utils");
const document_1 = require("../utils/document");
//
exports.defaultColumnSizing = {
    size: 150,
    minSize: 20,
    maxSize: Number.MAX_SAFE_INTEGER,
};
const getDefaultColumnSizingInfoState = () => ({
    startOffset: null,
    startSize: null,
    deltaOffset: null,
    deltaPercentage: null,
    isResizingColumn: false,
    columnSizingStart: [],
});
exports.ColumnSizing = {
    getDefaultColumnDef: () => {
        return exports.defaultColumnSizing;
    },
    getInitialState: (state) => {
        return {
            columnSizing: {},
            columnSizingInfo: getDefaultColumnSizingInfoState(),
            ...state,
        };
    },
    getDefaultOptions: (table) => {
        return {
            columnResizeMode: 'onEnd',
            columnResizeDirection: 'ltr',
            onColumnSizingChange: (0, utils_1.makeStateUpdater)('columnSizing', table),
            onColumnSizingInfoChange: (0, utils_1.makeStateUpdater)('columnSizingInfo', table),
        };
    },
    createColumn: (column, table) => {
        column.getSize = () => {
            var _a, _b, _c;
            const columnSize = table.getState().columnSizing[column.id];
            return Math.min(Math.max((_a = column.columnDef.minSize) !== null && _a !== void 0 ? _a : exports.defaultColumnSizing.minSize, (_b = columnSize !== null && columnSize !== void 0 ? columnSize : column.columnDef.size) !== null && _b !== void 0 ? _b : exports.defaultColumnSizing.size), (_c = column.columnDef.maxSize) !== null && _c !== void 0 ? _c : exports.defaultColumnSizing.maxSize);
        };
        column.getStart = (0, utils_1.memo)((position) => [
            position,
            (0, __1._getVisibleLeafColumns)(table, position),
            table.getState().columnSizing,
        ], (position, columns) => columns.slice(0, column.getIndex(position)).reduce((sum, col) => sum + col.getSize(), 0), (0, utils_1.getMemoOptions)(table.options, 'debugColumns', 'getStart'));
        column.getAfter = (0, utils_1.memo)((position) => [
            position,
            (0, __1._getVisibleLeafColumns)(table, position),
            table.getState().columnSizing,
        ], (position, columns) => columns.slice(column.getIndex(position) + 1).reduce((sum, col) => sum + col.getSize(), 0), (0, utils_1.getMemoOptions)(table.options, 'debugColumns', 'getAfter'));
        column.resetSize = () => {
            table.setColumnSizing(({ [column.id]: _, ...rest }) => {
                return rest;
            });
        };
        column.getCanResize = () => {
            var _a, _b;
            return (((_a = column.columnDef.enableResizing) !== null && _a !== void 0 ? _a : true) && ((_b = table.options.enableColumnResizing) !== null && _b !== void 0 ? _b : true));
        };
        column.getIsResizing = () => {
            return table.getState().columnSizingInfo.isResizingColumn === column.id;
        };
    },
    createHeader: (header, table) => {
        header.getSize = () => {
            let sum = 0;
            const recurse = (h) => {
                var _a;
                if (h.subHeaders.length) {
                    h.subHeaders.forEach(recurse);
                }
                else {
                    sum += (_a = h.column.getSize()) !== null && _a !== void 0 ? _a : 0;
                }
            };
            recurse(header);
            return sum;
        };
        header.getStart = () => {
            if (header.index > 0) {
                const prevSiblingHeader = header.headerGroup.headers[header.index - 1];
                return prevSiblingHeader.getStart() + prevSiblingHeader.getSize();
            }
            return 0;
        };
        header.getResizeHandler = (_contextDocument) => {
            const column = table.getColumn(header.column.id);
            const canResize = column === null || column === void 0 ? void 0 : column.getCanResize();
            return (e) => {
                var _a, _b;
                if (!column || !canResize) {
                    return;
                }
                (_b = (_a = e).persist) === null || _b === void 0 ? void 0 : _b.call(_a);
                if (isTouchStartEvent(e)) {
                    // lets not respond to multiple touches (e.g. 2 or 3 fingers)
                    if (e.touches && e.touches.length > 1) {
                        return;
                    }
                }
                const startSize = header.getSize();
                const columnSizingStart = header
                    ? header.getLeafHeaders().map((d) => [d.column.id, d.column.getSize()])
                    : [[column.id, column.getSize()]];
                const clientX = isTouchStartEvent(e)
                    ? Math.round(e.touches[0].clientX)
                    : e.clientX;
                const newColumnSizing = {};
                const updateOffset = (eventType, clientXPos) => {
                    if (typeof clientXPos !== 'number') {
                        return;
                    }
                    table.setColumnSizingInfo((old) => {
                        var _a, _b;
                        const deltaDirection = table.options.columnResizeDirection === 'rtl' ? -1 : 1;
                        const deltaOffset = (clientXPos - ((_a = old === null || old === void 0 ? void 0 : old.startOffset) !== null && _a !== void 0 ? _a : 0)) * deltaDirection;
                        const deltaPercentage = Math.max(deltaOffset / ((_b = old === null || old === void 0 ? void 0 : old.startSize) !== null && _b !== void 0 ? _b : 0), -0.999999);
                        old.columnSizingStart.forEach(([columnId, headerSize]) => {
                            newColumnSizing[columnId] =
                                Math.round(Math.max(headerSize + headerSize * deltaPercentage, 0) * 100) / 100;
                        });
                        return {
                            ...old,
                            deltaOffset,
                            deltaPercentage,
                        };
                    });
                    if (table.options.columnResizeMode === 'onChange' || eventType === 'end') {
                        table.setColumnSizing((old) => ({
                            ...old,
                            ...newColumnSizing,
                        }));
                    }
                };
                const onMove = (clientXPos) => updateOffset('move', clientXPos);
                const onEnd = (clientXPos) => {
                    updateOffset('end', clientXPos);
                    table.setColumnSizingInfo((old) => ({
                        ...old,
                        isResizingColumn: false,
                        startOffset: null,
                        startSize: null,
                        deltaOffset: null,
                        deltaPercentage: null,
                        columnSizingStart: [],
                    }));
                };
                const contextDocument = (0, document_1.safelyAccessDocument)(_contextDocument);
                const mouseEvents = {
                    moveHandler: (moveEv) => onMove(moveEv.clientX),
                    upHandler: (upEv) => {
                        contextDocument === null || contextDocument === void 0 ? void 0 : contextDocument.removeEventListener('mousemove', mouseEvents.moveHandler);
                        contextDocument === null || contextDocument === void 0 ? void 0 : contextDocument.removeEventListener('mouseup', mouseEvents.upHandler);
                        onEnd(upEv.clientX);
                    },
                };
                const touchEvents = {
                    moveHandler: (moveEv) => {
                        if (moveEv.cancelable) {
                            moveEv.preventDefault();
                            moveEv.stopPropagation();
                        }
                        onMove(moveEv.touches[0].clientX);
                        return false;
                    },
                    upHandler: (upEv) => {
                        var _a;
                        contextDocument === null || contextDocument === void 0 ? void 0 : contextDocument.removeEventListener('touchmove', touchEvents.moveHandler);
                        contextDocument === null || contextDocument === void 0 ? void 0 : contextDocument.removeEventListener('touchend', touchEvents.upHandler);
                        if (upEv.cancelable) {
                            upEv.preventDefault();
                            upEv.stopPropagation();
                        }
                        onEnd((_a = upEv.touches[0]) === null || _a === void 0 ? void 0 : _a.clientX);
                    },
                };
                const passiveIfSupported = passiveEventSupported() ? { passive: false } : false;
                if (isTouchStartEvent(e)) {
                    contextDocument === null || contextDocument === void 0 ? void 0 : contextDocument.addEventListener('touchmove', touchEvents.moveHandler, passiveIfSupported);
                    contextDocument === null || contextDocument === void 0 ? void 0 : contextDocument.addEventListener('touchend', touchEvents.upHandler, passiveIfSupported);
                }
                else {
                    contextDocument === null || contextDocument === void 0 ? void 0 : contextDocument.addEventListener('mousemove', mouseEvents.moveHandler, passiveIfSupported);
                    contextDocument === null || contextDocument === void 0 ? void 0 : contextDocument.addEventListener('mouseup', mouseEvents.upHandler, passiveIfSupported);
                }
                table.setColumnSizingInfo((old) => ({
                    ...old,
                    startOffset: clientX,
                    startSize,
                    deltaOffset: 0,
                    deltaPercentage: 0,
                    columnSizingStart,
                    isResizingColumn: column.id,
                }));
            };
        };
    },
    createTable: (table) => {
        table.setColumnSizing = (updater) => { var _a, _b; return (_b = (_a = table.options).onColumnSizingChange) === null || _b === void 0 ? void 0 : _b.call(_a, updater); };
        table.setColumnSizingInfo = (updater) => { var _a, _b; return (_b = (_a = table.options).onColumnSizingInfoChange) === null || _b === void 0 ? void 0 : _b.call(_a, updater); };
        table.resetColumnSizing = (defaultState) => {
            var _a;
            table.setColumnSizing(defaultState ? {} : ((_a = table.initialState.columnSizing) !== null && _a !== void 0 ? _a : {}));
        };
        table.resetHeaderSizeInfo = (defaultState) => {
            var _a;
            table.setColumnSizingInfo(defaultState
                ? getDefaultColumnSizingInfoState()
                : ((_a = table.initialState.columnSizingInfo) !== null && _a !== void 0 ? _a : getDefaultColumnSizingInfoState()));
        };
        table.getTotalSize = () => {
            var _a, _b;
            return (_b = (_a = table.getHeaderGroups()[0]) === null || _a === void 0 ? void 0 : _a.headers.reduce((sum, header) => {
                return sum + header.getSize();
            }, 0)) !== null && _b !== void 0 ? _b : 0;
        };
        table.getLeftTotalSize = () => {
            var _a, _b;
            return (_b = (_a = table.getLeftHeaderGroups()[0]) === null || _a === void 0 ? void 0 : _a.headers.reduce((sum, header) => {
                return sum + header.getSize();
            }, 0)) !== null && _b !== void 0 ? _b : 0;
        };
        table.getCenterTotalSize = () => {
            var _a, _b;
            return (_b = (_a = table.getCenterHeaderGroups()[0]) === null || _a === void 0 ? void 0 : _a.headers.reduce((sum, header) => {
                return sum + header.getSize();
            }, 0)) !== null && _b !== void 0 ? _b : 0;
        };
        table.getRightTotalSize = () => {
            var _a, _b;
            return (_b = (_a = table.getRightHeaderGroups()[0]) === null || _a === void 0 ? void 0 : _a.headers.reduce((sum, header) => {
                return sum + header.getSize();
            }, 0)) !== null && _b !== void 0 ? _b : 0;
        };
    },
};
let passiveSupported = null;
function passiveEventSupported() {
    if (typeof passiveSupported === 'boolean')
        return passiveSupported;
    let supported = false;
    try {
        const options = {
            get passive() {
                supported = true;
                return false;
            },
        };
        const noop = () => { };
        window.addEventListener('test', noop, options);
        window.removeEventListener('test', noop);
    }
    catch (err) {
        supported = false;
    }
    passiveSupported = supported;
    return passiveSupported;
}
function isTouchStartEvent(e) {
    return e.type === 'touchstart';
}
