import { isNumber, isValid } from "@visactor/vutils";

import { Group } from "../graphic/group";

import { updateCell } from "../group-creater/cell-helper";

import { getCellMergeInfo } from "../utils/get-cell-merge";

import { deduplication } from "../../tools/util";

import { checkHaveTextStick, resetTextStick } from "../stick-text";

export function updateRow(removeCells, addCells, updateCells, table, skipUpdateProxy) {
    var _a, _b;
    checkHaveTextStick(table) && resetTextStick(table);
    const scene = table.scenegraph, removeRows = deduplication(removeCells.map((cell => cell.row))).sort(((a, b) => b - a)), addRows = deduplication(addCells.map((cell => cell.row))).sort(((a, b) => a - b)), updateRows = deduplication(updateCells.map((cell => cell.row))).sort(((a, b) => a - b));
    let rowUpdatePos;
    if (updateRows.length) {
        rowUpdatePos = _getUpdateRowIndexUseCellNode(updateRows[0] - 1, updateRows[updateRows.length - 1] + 1, scene);
    }
    if (addRows.length) {
        const pos = _getUpdateRowIndexUseCellNode(addRows[0] - 1, addRows[addRows.length - 1] + 1, scene);
        rowUpdatePos = isValid(rowUpdatePos) ? isValid(pos) ? Math.min(rowUpdatePos, pos) : rowUpdatePos : pos;
    }
    if (removeRows.length) {
        const pos = _getUpdateRowIndexUseCellNode(removeRows[0] - 1, removeRows[removeRows.length - 1] + 1, scene);
        rowUpdatePos = isValid(rowUpdatePos) ? isValid(pos) ? Math.min(rowUpdatePos, pos) : rowUpdatePos : pos;
    }
    removeRows.forEach((row => {
        removeRow(row, scene, skipUpdateProxy);
    }));
    const rowHeightsMap = table.rowHeightsMap;
    if (removeRows.forEach((row => {
        rowHeightsMap.delete(row);
    })), removeRows.length) {
        resetRowNumber(scene);
        const pos = _getUpdateRowIndex(removeRows[removeRows.length - 1] - 1, removeRows[0] - removeRows.length + 1, scene);
        rowUpdatePos = isValid(rowUpdatePos) ? isValid(pos) ? Math.min(rowUpdatePos, pos) : rowUpdatePos : pos;
    }
    let updateAfter;
    if (scene.table._clearRowRangeHeightsMap(), addRows.forEach((row => {
        const needUpdateAfter = addRow(row, scene, skipUpdateProxy);
        updateAfter = null != updateAfter ? updateAfter : needUpdateAfter, rowHeightsMap.insert(row);
    })), resetRowNumberAndY(scene), addRows.length) {
        const pos = _getUpdateRowIndex(addRows[0] - 1, addRows[addRows.length - 1] + 1, scene);
        rowUpdatePos = isValid(rowUpdatePos) ? isValid(pos) ? Math.min(rowUpdatePos, pos) : rowUpdatePos : pos;
    }
    const batchMergePos = new Set;
    for (let col = 0; col < table.colCount; col++) updateRows.forEach((row => {
        if (row < table.frozenRowCount) {
            const mergeInfo = getCellMergeInfo(scene.table, col, row);
            if (mergeInfo) for (let col = mergeInfo.start.col; col <= mergeInfo.end.col; col++) for (let row = mergeInfo.start.row; row <= mergeInfo.end.row; row++) {
                const key = `${col}-${row}`;
                batchMergePos.has(key) || (updateCell(col, row, scene.table, !1), batchMergePos.add(key));
            } else updateCell(col, row, scene.table, !1);
        } else if (row > table.rowCount - 1 || row < scene.table.rowCount - scene.table.bottomFrozenRowCount && (row < scene.proxy.rowStart || row > scene.proxy.rowEnd)) removeCellGroup(row, scene); else {
            const mergeInfo = getCellMergeInfo(scene.table, col, row);
            if (mergeInfo) for (let col = mergeInfo.start.col; col <= mergeInfo.end.col; col++) for (let row = mergeInfo.start.row; row <= mergeInfo.end.row; row++) {
                const key = `${col}-${row}`;
                batchMergePos.has(key) || (updateCell(col, row, scene.table, !1), batchMergePos.add(key));
            } else updateCell(col, row, scene.table, !1);
        }
    }));
    if (updateRows.length) {
        const pos = _getUpdateRowIndex(updateRows[0] - 1, updateRows[updateRows.length - 1] + 1, scene);
        rowUpdatePos = isValid(rowUpdatePos) ? isValid(pos) ? Math.min(rowUpdatePos, pos) : rowUpdatePos : pos;
    }
    if (isNumber(updateAfter)) {
        for (let col = 0; col < Math.max(table.colCount, null !== (_a = table.internalProps._oldColCount) && void 0 !== _a ? _a : table.colCount); col++) for (let row = updateAfter; row < Math.max(table.rowCount, null !== (_b = table.internalProps._oldRowCount) && void 0 !== _b ? _b : table.rowCount); row++) {
            const cellGroup = scene.highPerformanceGetCell(col, row, !0);
            cellGroup && (cellGroup.needUpdate = !0);
        }
        rowUpdatePos = isValid(rowUpdatePos) ? isValid(updateAfter) ? Math.min(rowUpdatePos, updateAfter) : rowUpdatePos : updateAfter;
    }
    if (isNumber(rowUpdatePos) && (scene.proxy.rowUpdatePos = Math.min(scene.proxy.rowUpdatePos, rowUpdatePos)), 
    addRows.length) {
        if (!isNumber(updateAfter)) {
            const minRow = Math.min(...addRows);
            scene.proxy.rowUpdatePos = Math.min(minRow, scene.proxy.rowUpdatePos);
        }
        scene.proxy.rowUpdateDirection = "up", scene.proxy.updateCellGroups(2 * scene.proxy.screenRowCount), 
        updateBottomFrozeCellGroups();
    } else removeRows.length && (setRowSeriesNumberCellNeedUpdate(removeRows[removeRows.length - 1], scene), 
    scene.proxy.updateCellGroups(2 * scene.proxy.screenRowCount), updateBottomFrozeCellGroups());
    scene.proxy.progress();
    const newTotalHeight = table.getRowsHeight(table.frozenRowCount, table.rowCount - 1 - table.bottomFrozenRowCount);
    function updateBottomFrozeCellGroups() {
        if ((null == addRows ? void 0 : addRows[(null == addRows ? void 0 : addRows.length) - 1]) >= table.rowCount - table.bottomFrozenRowCount || (null == updateRows ? void 0 : updateRows[(null == updateRows ? void 0 : updateRows.length) - 1]) >= table.rowCount - table.bottomFrozenRowCount || (null == removeRows ? void 0 : removeRows[0]) >= table.rowCount - table.bottomFrozenRowCount) {
            for (let col = 0; col < table.colCount; col++) for (let row = table.rowCount - table.bottomFrozenRowCount; row < table.rowCount; row++) {
                const cellGroup = scene.highPerformanceGetCell(col, row, !0);
                cellGroup && (cellGroup.needUpdate = !0);
            }
            scene.proxy.updateBottomFrozenCellGroups();
        }
    }
    scene.updateContainerHeight(scene.table.frozenRowCount, newTotalHeight - scene.bodyGroup.attribute.height);
}

function removeRow(row, scene, skipUpdateProxy) {
    const proxy = scene.proxy;
    if (row >= proxy.rowStart && row <= proxy.rowEnd && (removeCellGroup(row, scene), 
    proxy.rowEnd--, proxy.currentRow--), !skipUpdateProxy) {
        proxy.bodyBottomRow--;
        const totalActualBodyRowCount = Math.min(proxy.rowLimit, proxy.bodyBottomRow - proxy.bodyTopRow + 1);
        proxy.totalActualBodyRowCount = totalActualBodyRowCount, proxy.totalRow = Math.min(proxy.table.rowCount - 1, proxy.rowStart + totalActualBodyRowCount - 1);
    }
}

function addRow(row, scene, skipUpdateProxy) {
    const proxy = scene.proxy;
    if (!skipUpdateProxy) {
        proxy.bodyBottomRow++;
        const totalActualBodyRowCount = Math.min(proxy.rowLimit, proxy.bodyBottomRow - proxy.bodyTopRow + 1);
        proxy.totalActualBodyRowCount = totalActualBodyRowCount, proxy.totalRow = proxy.rowStart + totalActualBodyRowCount - 1;
    }
    if (!(row < proxy.rowStart)) return row > proxy.rowEnd ? proxy.rowEnd - proxy.rowStart + 1 < proxy.rowLimit ? (proxy.rowEnd++, 
    proxy.currentRow++, addRowCellGroup(row, scene), row) : void 0 : proxy.rowEnd - proxy.rowStart + 1 < proxy.rowLimit ? (proxy.rowEnd++, 
    proxy.currentRow++, addRowCellGroup(row, scene), row) : row;
}

function resetRowNumber(scene) {
    function processCell(cellGroup, rowIndex) {
        cellGroup.row = rowIndex;
        const merge = getCellMergeInfo(scene.table, cellGroup.col, cellGroup.row);
        merge ? (cellGroup.mergeStartCol = merge.start.col, cellGroup.mergeEndCol = merge.end.col, 
        cellGroup.mergeStartRow = merge.start.row, cellGroup.mergeEndRow = merge.end.row) : (cellGroup.mergeStartCol = void 0, 
        cellGroup.mergeEndCol = void 0, cellGroup.mergeStartRow = void 0, cellGroup.mergeEndRow = void 0);
    }
    scene.bodyGroup.forEachChildren((colGroup => {
        let rowIndex = scene.bodyRowStart;
        null == colGroup || colGroup.forEachChildren((cellGroup => {
            processCell(cellGroup, rowIndex), rowIndex++;
        }));
    })), scene.rowHeaderGroup.forEachChildren((colGroup => {
        let rowIndex = scene.bodyRowStart;
        null == colGroup || colGroup.forEachChildren((cellGroup => {
            processCell(cellGroup, rowIndex), rowIndex++;
        }));
    })), scene.rightFrozenGroup.forEachChildren((colGroup => {
        let rowIndex = scene.bodyRowStart;
        null == colGroup || colGroup.forEachChildren((cellGroup => {
            processCell(cellGroup, rowIndex), rowIndex++;
        }));
    })), scene.bottomFrozenGroup.forEachChildren((colGroup => {
        let rowIndex = scene.table.rowCount - scene.table.bottomFrozenRowCount;
        null == colGroup || colGroup.forEachChildren((cellGroup => {
            processCell(cellGroup, rowIndex), rowIndex++;
        }));
    })), scene.leftBottomCornerGroup.forEachChildren((colGroup => {
        let rowIndex = scene.table.rowCount - scene.table.bottomFrozenRowCount;
        null == colGroup || colGroup.forEachChildren((cellGroup => {
            processCell(cellGroup, rowIndex), rowIndex++;
        }));
    })), scene.rightBottomCornerGroup.forEachChildren((colGroup => {
        let rowIndex = scene.table.rowCount - scene.table.bottomFrozenRowCount;
        null == colGroup || colGroup.forEachChildren((cellGroup => {
            processCell(cellGroup, rowIndex), rowIndex++;
        }));
    }));
}

function resetRowNumberAndY(scene) {
    function processCell(cellGroup, rowIndex, y) {
        cellGroup.row = rowIndex, cellGroup.setAttribute("y", y);
        const merge = getCellMergeInfo(scene.table, cellGroup.col, cellGroup.row);
        merge ? (cellGroup.mergeStartCol = merge.start.col, cellGroup.mergeEndCol = merge.end.col, 
        cellGroup.mergeStartRow = merge.start.row, cellGroup.mergeEndRow = merge.end.row) : (cellGroup.mergeStartCol = void 0, 
        cellGroup.mergeEndCol = void 0, cellGroup.mergeStartRow = void 0, cellGroup.mergeEndRow = void 0);
    }
    scene.bodyGroup.forEachChildren((colGroup => {
        let rowIndex = scene.bodyRowStart, y = scene.getCellGroupY(rowIndex);
        null == colGroup || colGroup.forEachChildren((cellGroup => {
            processCell(cellGroup, rowIndex, y), rowIndex++, y += cellGroup.attribute.height;
        }));
    })), scene.rowHeaderGroup.forEachChildren((colGroup => {
        let rowIndex = scene.bodyRowStart, y = scene.getCellGroupY(rowIndex);
        null == colGroup || colGroup.forEachChildren((cellGroup => {
            processCell(cellGroup, rowIndex, y), rowIndex++, y += cellGroup.attribute.height;
        }));
    })), scene.rightFrozenGroup.forEachChildren((colGroup => {
        let rowIndex = scene.bodyRowStart, y = scene.getCellGroupY(rowIndex);
        null == colGroup || colGroup.forEachChildren((cellGroup => {
            processCell(cellGroup, rowIndex, y), rowIndex++, y += cellGroup.attribute.height;
        }));
    })), scene.bottomFrozenGroup.forEachChildren((colGroup => {
        let rowIndex = scene.table.rowCount - scene.table.bottomFrozenRowCount, y = 0;
        null == colGroup || colGroup.forEachChildren((cellGroup => {
            processCell(cellGroup, rowIndex, y), rowIndex++, y += cellGroup.attribute.height;
        }));
    })), scene.leftBottomCornerGroup.forEachChildren((colGroup => {
        let rowIndex = scene.table.rowCount - scene.table.bottomFrozenRowCount, y = 0;
        null == colGroup || colGroup.forEachChildren((cellGroup => {
            processCell(cellGroup, rowIndex, y), rowIndex++, y += cellGroup.attribute.height;
        }));
    })), scene.rightBottomCornerGroup.forEachChildren((colGroup => {
        let rowIndex = scene.table.rowCount - scene.table.bottomFrozenRowCount, y = 0;
        null == colGroup || colGroup.forEachChildren((cellGroup => {
            processCell(cellGroup, rowIndex, y), rowIndex++, y += cellGroup.attribute.height;
        }));
    }));
}

function addRowCellGroup(row, scene) {
    for (let col = 0; col < scene.table.colCount; col++) {
        const cellGroup = new Group({
            x: 0,
            y: 0,
            width: scene.table.getColWidth(col),
            height: scene.table.getRowHeight(row)
        });
        if (cellGroup.role = "cell", cellGroup.col = col, cellGroup.row = row, cellGroup.needUpdate = !0, 
        !cellGroup) continue;
        const colGroup = scene.getColGroup(col);
        if (colGroup) if (colGroup.firstChild && row < colGroup.firstChild.row) colGroup.insertBefore(cellGroup, colGroup.firstChild), 
        colGroup.firstChild.row = colGroup.firstChild.row + 1; else if (colGroup.lastChild && row > colGroup.lastChild.row) colGroup.appendChild(cellGroup); else {
            const cellBefore = scene.highPerformanceGetCell(col, row, !0);
            cellBefore !== cellGroup && (colGroup.insertBefore(cellGroup, cellBefore), cellBefore && (cellBefore.row = cellBefore.row + 1), 
            cellBefore !== colGroup.lastChild && colGroup.lastChild && (colGroup.lastChild.row = colGroup.lastChild.row + 1));
        }
    }
}

function removeCellGroup(row, scene) {
    for (let col = 0; col < scene.table.colCount; col++) {
        const colGroup = scene.getColGroup(col, !1);
        if (!colGroup) continue;
        let cellGroup;
        colGroup.forEachChildren((cell => cell.row === row && (cellGroup = cell, !0))), 
        cellGroup && (colGroup.updateColumnHeight(-cellGroup.attribute.height), colGroup.removeChild(cellGroup));
    }
}

function _getUpdateRowIndex(beforeRow, afterRow, scene) {
    let updateRow;
    for (let col = 0; col < scene.table.colCount; col++) {
        const rangeBefore = scene.table.getCellRange(col, beforeRow);
        let row;
        rangeBefore.start.row <= beforeRow + 1 && rangeBefore.end.row >= beforeRow + 1 && (addNeedUpdateTag(rangeBefore, scene), 
        row = rangeBefore.start.row);
        const rangeAfter = scene.table.getCellRange(col, afterRow);
        rangeAfter.start.row <= afterRow + 1 && rangeAfter.end.row >= afterRow + 1 && (addNeedUpdateTag(rangeAfter, scene), 
        row = rangeAfter.start.row), isValid(row) && (updateRow = isValid(updateRow) ? Math.min(updateRow, row) : row);
    }
    return updateRow;
}

function _getUpdateRowIndexUseCellNode(beforeRow, afterRow, scene) {
    let updateRow;
    for (let col = 0; col < scene.table.colCount; col++) {
        let row;
        const beforeCell = scene.highPerformanceGetCell(col, beforeRow);
        beforeCell.mergeStartRow && beforeCell.mergeEndRow && beforeCell.mergeEndRow > beforeRow && (addNeedUpdateTag({
            start: {
                row: beforeCell.mergeStartRow,
                col: scene.table.isAutoRowHeight(afterRow) ? 0 : beforeCell.mergeStartCol
            },
            end: {
                row: beforeCell.mergeEndRow,
                col: scene.table.isAutoRowHeight(afterRow) ? scene.table.colCount - 1 : beforeCell.mergeEndCol
            }
        }, scene), row = beforeCell.mergeStartRow);
        const afterCell = scene.highPerformanceGetCell(col, afterRow);
        afterCell.mergeStartRow && afterCell.mergeEndRow && afterCell.mergeStartRow < afterRow && (addNeedUpdateTag({
            start: {
                row: afterCell.mergeStartRow,
                col: scene.table.isAutoRowHeight(afterRow) ? 0 : afterCell.mergeStartCol
            },
            end: {
                row: afterCell.mergeEndRow,
                col: scene.table.isAutoRowHeight(afterRow) ? scene.table.colCount - 1 : afterCell.mergeEndCol
            }
        }, scene), row = afterCell.mergeStartRow), isValid(row) && (updateRow = isValid(updateRow) ? Math.min(updateRow, row) : row);
    }
    return updateRow;
}

function addNeedUpdateTag(range, scene) {
    const {start: start, end: end} = range;
    for (let col = start.col; col <= end.col; col++) for (let row = start.row; row <= end.row; row++) {
        const cellGroup = scene.highPerformanceGetCell(col, row, !0);
        cellGroup && (cellGroup.needUpdate = !0);
    }
}

function setRowSeriesNumberCellNeedUpdate(startUpdateRow, scene) {
    if (scene.table.isHasSeriesNumber()) for (let row = startUpdateRow; row <= scene.table.rowCount - 1; row++) updateCell(0, row, scene.table, !1);
}
//# sourceMappingURL=update-row.js.map
