import { appendTrackedReverseEdge, parseQualifiedDependencySheetName, removeTrackedReverseEdge, } from './formula-binding-dependency-helpers.js';
function referencedSheetsForCompiled(compiled) {
    const parsedDeps = compiled.parsedDeps;
    let sheets;
    if (parsedDeps !== undefined && parsedDeps.length === compiled.deps.length) {
        for (let index = 0; index < parsedDeps.length; index += 1) {
            const dependency = parsedDeps[index];
            if (dependency.sheetName) {
                ;
                (sheets ??= new Set()).add(dependency.sheetName);
            }
            if (dependency.kind === 'range' && dependency.sheetEndName) {
                ;
                (sheets ??= new Set()).add(dependency.sheetEndName);
            }
        }
        return sheets === undefined ? [] : [...sheets];
    }
    sheets = new Set();
    parsedDeps?.forEach((dependency) => {
        if (dependency.sheetName) {
            sheets.add(dependency.sheetName);
        }
        if (dependency.kind === 'range' && dependency.sheetEndName) {
            sheets.add(dependency.sheetEndName);
        }
    });
    compiled.deps.forEach((dependency, index) => {
        const parsedDependency = compiled.parsedDeps?.[index];
        if (parsedDependency?.kind === 'range' && parsedDependency.sheetEndName) {
            return;
        }
        const sheetName = parseQualifiedDependencySheetName(dependency);
        if (sheetName) {
            sheets.add(sheetName);
        }
    });
    return [...sheets];
}
const EMPTY_MOVED_CELL_SET = new Set();
function moveSet(registry, oldKey, newKey) {
    const candidates = registry.get(oldKey);
    if (!candidates || candidates.size === 0) {
        return EMPTY_MOVED_CELL_SET;
    }
    const existing = registry.get(newKey);
    if (existing) {
        candidates.forEach((cellIndex) => {
            existing.add(cellIndex);
        });
    }
    else {
        registry.set(newKey, candidates);
    }
    registry.delete(oldKey);
    return candidates;
}
export function createFormulaBindingSheetIndex() {
    const ownerSheetCells = new Map();
    const ownerSheetRuns = new Map();
    const referencedSheetCells = new Map();
    const materializeOwnerSheetSet = (sheetName) => {
        const runs = ownerSheetRuns.get(sheetName);
        let owners = ownerSheetCells.get(sheetName);
        if (!runs || runs.length === 0) {
            return owners;
        }
        if (!owners) {
            owners = new Set();
            ownerSheetCells.set(sheetName, owners);
        }
        for (const run of runs) {
            for (let index = 0; index < run.length; index += 1) {
                owners.add(run[index]);
            }
        }
        ownerSheetRuns.delete(sheetName);
        return owners;
    };
    const removeOwner = (sheetName, cellIndex) => {
        materializeOwnerSheetSet(sheetName);
        removeTrackedReverseEdge(ownerSheetCells, sheetName, cellIndex);
    };
    const moveOwnerSheetName = (oldSheetName, newSheetName) => {
        const ownerRuns = ownerSheetRuns.get(oldSheetName);
        if (ownerRuns && ownerRuns.length > 0) {
            const existingOwnerRuns = ownerSheetRuns.get(newSheetName);
            if (existingOwnerRuns) {
                existingOwnerRuns.push(...ownerRuns);
            }
            else {
                ownerSheetRuns.set(newSheetName, ownerRuns);
            }
            ownerSheetRuns.delete(oldSheetName);
        }
        return moveSet(ownerSheetCells, oldSheetName, newSheetName);
    };
    const moveReferenceSheetName = (oldSheetName, newSheetName) => {
        return moveSet(referencedSheetCells, oldSheetName, newSheetName);
    };
    return {
        clear() {
            ownerSheetCells.clear();
            ownerSheetRuns.clear();
            referencedSheetCells.clear();
        },
        trackFormula(cellIndex, ownerSheetName, compiled) {
            appendTrackedReverseEdge(ownerSheetCells, ownerSheetName, cellIndex);
            referencedSheetsForCompiled(compiled).forEach((sheetName) => {
                appendTrackedReverseEdge(referencedSheetCells, sheetName, cellIndex);
            });
        },
        trackFormulaOwnerRun(ownerSheetName, cellIndices) {
            const runs = ownerSheetRuns.get(ownerSheetName);
            if (runs) {
                runs.push(cellIndices);
            }
            else {
                ownerSheetRuns.set(ownerSheetName, [cellIndices]);
            }
        },
        untrackFormula(cellIndex, ownerSheetName, compiled) {
            if (ownerSheetName) {
                removeOwner(ownerSheetName, cellIndex);
            }
            if (!compiled) {
                return;
            }
            referencedSheetsForCompiled(compiled).forEach((sheetName) => {
                removeTrackedReverseEdge(referencedSheetCells, sheetName, cellIndex);
            });
        },
        moveOwnerSheetName(oldSheetName, newSheetName) {
            return moveOwnerSheetName(oldSheetName, newSheetName);
        },
        moveReferenceSheetName(oldSheetName, newSheetName) {
            return moveReferenceSheetName(oldSheetName, newSheetName);
        },
        moveSheetName(oldSheetName, newSheetName) {
            return {
                owners: moveOwnerSheetName(oldSheetName, newSheetName),
                references: moveReferenceSheetName(oldSheetName, newSheetName),
            };
        },
        getOwnedBySheetSet(sheetName) {
            return materializeOwnerSheetSet(sheetName);
        },
        getReferencingSheetSet(sheetName) {
            return referencedSheetCells.get(sheetName);
        },
        appendOwner(sheetName, cellIndex) {
            appendTrackedReverseEdge(ownerSheetCells, sheetName, cellIndex);
        },
        removeOwner(sheetName, cellIndex) {
            removeOwner(sheetName, cellIndex);
        },
        appendReference(sheetName, cellIndex) {
            appendTrackedReverseEdge(referencedSheetCells, sheetName, cellIndex);
        },
        removeReference(sheetName, cellIndex) {
            removeTrackedReverseEdge(referencedSheetCells, sheetName, cellIndex);
        },
        collectOwnedBySheet(sheetName) {
            return [...(materializeOwnerSheetSet(sheetName) ?? [])];
        },
        collectReferencingSheet(sheetName) {
            return [...(referencedSheetCells.get(sheetName) ?? [])];
        },
    };
}
//# sourceMappingURL=formula-binding-sheet-index.js.map