import { formatAddress, parseCellAddress } from '@bilig/formula';
const normalizedRecordsByRangeArray = new WeakMap();
export function cloneWorkbookRangeRecords(records, cloneRecord) {
    return records.map((record) => cloneRecord(canonicalWorkbookRangeRef(record.range), record));
}
export function overlayWorkbookRangeRecords(records, nextRecord, cloneRecord, isDefaultRecord) {
    const normalizedNext = cloneRecord(canonicalWorkbookRangeRef(nextRecord.range), nextRecord);
    const remainders = records.flatMap((record) => subtractWorkbookRangeRecord(record.range, normalizedNext.range).map((remainder) => cloneRecord(remainder, record)));
    return isDefaultRecord(normalizedNext) ? remainders : [...remainders, normalizedNext];
}
export function replaceWorkbookRangeRecords(records, cloneRecord, validateRecord) {
    const nextRecords = records.map((record) => cloneRecord(canonicalWorkbookRangeRef(record.range), record));
    nextRecords.forEach((record) => {
        validateRecord(record);
    });
    return nextRecords;
}
export function findWorkbookRangeRecord(records, row, col) {
    const normalizedRecords = getNormalizedWorkbookRangeRecords(records);
    for (let index = normalizedRecords.length - 1; index >= 0; index -= 1) {
        const normalized = normalizedRecords[index];
        if (normalized.startRow <= row && normalized.endRow >= row && normalized.startCol <= col && normalized.endCol >= col) {
            return records[normalized.recordIndex];
        }
    }
    return undefined;
}
function getNormalizedWorkbookRangeRecords(records) {
    const cached = normalizedRecordsByRangeArray.get(records);
    if (cached && cached.length === records.length) {
        return cached;
    }
    const normalizedRecords = records.map((record, recordIndex) => ({
        ...normalizeWorkbookRangeRef(record.range),
        recordIndex,
    }));
    normalizedRecordsByRangeArray.set(records, normalizedRecords);
    return normalizedRecords;
}
function normalizeWorkbookRangeRef(range) {
    const start = parseCellAddress(range.startAddress, range.sheetName);
    const end = parseCellAddress(range.endAddress, range.sheetName);
    const startRow = Math.min(start.row, end.row);
    const endRow = Math.max(start.row, end.row);
    const startCol = Math.min(start.col, end.col);
    const endCol = Math.max(start.col, end.col);
    return {
        sheetName: range.sheetName,
        startAddress: formatAddress(startRow, startCol),
        endAddress: formatAddress(endRow, endCol),
        startRow,
        endRow,
        startCol,
        endCol,
    };
}
export function canonicalWorkbookRangeRef(range) {
    return toPlainWorkbookRangeRef(normalizeWorkbookRangeRef(range));
}
export function canonicalWorkbookAddress(sheetName, address) {
    const parsed = parseCellAddress(address, sheetName);
    return formatAddress(parsed.row, parsed.col);
}
function subtractWorkbookRangeRecord(existing, cut) {
    if (existing.sheetName !== cut.sheetName) {
        return [toPlainWorkbookRangeRef(existing)];
    }
    const source = normalizeWorkbookRangeRef(existing);
    const removal = normalizeWorkbookRangeRef(cut);
    const startRow = Math.max(source.startRow, removal.startRow);
    const endRow = Math.min(source.endRow, removal.endRow);
    const startCol = Math.max(source.startCol, removal.startCol);
    const endCol = Math.min(source.endCol, removal.endCol);
    if (startRow > endRow || startCol > endCol) {
        return [toPlainWorkbookRangeRef(source)];
    }
    const remainders = [];
    const pushRemainder = (rowStart, rowEnd, colStart, colEnd) => {
        if (rowStart > rowEnd || colStart > colEnd) {
            return;
        }
        remainders.push({
            sheetName: source.sheetName,
            startAddress: formatAddress(rowStart, colStart),
            endAddress: formatAddress(rowEnd, colEnd),
        });
    };
    pushRemainder(source.startRow, startRow - 1, source.startCol, source.endCol);
    pushRemainder(endRow + 1, source.endRow, source.startCol, source.endCol);
    pushRemainder(startRow, endRow, source.startCol, startCol - 1);
    pushRemainder(startRow, endRow, endCol + 1, source.endCol);
    return remainders;
}
function toPlainWorkbookRangeRef(range) {
    return {
        sheetName: range.sheetName,
        startAddress: range.startAddress,
        endAddress: range.endAddress,
    };
}
//# sourceMappingURL=workbook-range-records.js.map