import { makeCellKey } from './workbook-cell-key-index.js';
import { hasWorkbookMetadataForSheetRename } from './workbook-store-metadata-presence.js';
import { createWorkbookSheetRecord } from './workbook-sheet-record.js';
export class WorkbookSheetRegistryStore {
    options;
    nextSheetId = 1;
    constructor(options) {
        this.options = options;
    }
    createSheet(name, order = this.options.sheetsByName.size, id) {
        const existing = this.options.sheetsByName.get(name);
        if (existing) {
            this.moveExistingSheet(existing, order);
            if (id !== undefined && existing.id !== id) {
                this.options.sheetsById.delete(existing.id);
                existing.id = id;
                existing.logical.setSheetId(id);
                this.options.sheetsById.set(existing.id, existing);
                this.bumpSheetId(id);
            }
            return existing;
        }
        const sheetId = id ?? this.nextSheetId++;
        const sheet = createWorkbookSheetRecord({
            id: sheetId,
            name,
            order,
            counters: this.options.counters,
        });
        if (id !== undefined) {
            this.bumpSheetId(id);
        }
        this.options.sheetsByName.set(name, sheet);
        this.options.sheetsById.set(sheet.id, sheet);
        return sheet;
    }
    moveSheet(name, order) {
        const sheet = this.options.sheetsByName.get(name);
        if (!sheet) {
            return undefined;
        }
        this.moveExistingSheet(sheet, order);
        return sheet;
    }
    deleteSheet(name) {
        const sheet = this.options.sheetsByName.get(name);
        if (!sheet) {
            return;
        }
        sheet.grid.forEachCell((cellIndex) => {
            const position = this.options.getCellPosition(cellIndex);
            if (position) {
                this.options.cellKeyToIndex.delete(makeCellKey(sheet.id, position.row, position.col));
            }
            this.options.cellFormats.delete(cellIndex);
            const identity = sheet.logical.getCellIdentity(cellIndex);
            if (identity) {
                sheet.logical.deleteVisibleCellByIds(identity.rowId, identity.colId);
            }
        });
        this.options.deleteSheetRecords(name, sheetDeletionMetadataContext([...this.options.sheetsByName.values()], name));
        sheet.rowAxis.length = 0;
        sheet.columnAxis.length = 0;
        sheet.styleRanges.length = 0;
        sheet.formatRanges.length = 0;
        delete sheet.arrayFormulas;
        delete sheet.dataTableFormulas;
        delete sheet.sheetPr;
        delete sheet.ignoredErrors;
        delete sheet.printPageSetup;
        delete sheet.printerSettings;
        delete sheet.sparklines;
        delete sheet.controlArtifacts;
        delete sheet.richTextArtifacts;
        delete sheet.cellMetadataRefs;
        this.options.sheetsByName.delete(name);
        this.options.sheetsById.delete(sheet.id);
    }
    renameSheet(oldName, nextName) {
        const trimmedName = nextName.trim();
        if (trimmedName.length === 0) {
            throw new Error('Sheet name must be non-empty');
        }
        const sheet = this.options.sheetsByName.get(oldName);
        if (!sheet) {
            return undefined;
        }
        if (oldName === trimmedName) {
            return sheet;
        }
        if (this.options.sheetsByName.has(trimmedName)) {
            return undefined;
        }
        return this.renameExistingSheet(sheet, oldName, trimmedName);
    }
    renameSheetById(sheetId, trimmedName) {
        if (trimmedName.length === 0) {
            throw new Error('Sheet name must be non-empty');
        }
        const sheet = this.options.sheetsById.get(sheetId);
        if (!sheet) {
            return undefined;
        }
        const oldName = sheet.name;
        if (oldName === trimmedName) {
            return sheet;
        }
        if (this.options.sheetsByName.has(trimmedName)) {
            return undefined;
        }
        return this.renameExistingSheet(sheet, oldName, trimmedName);
    }
    renameSheetByIdTrustedPrevalidated(sheetId, oldName, trimmedName) {
        const sheet = this.options.sheetsById.get(sheetId);
        if (!sheet || sheet.name !== oldName) {
            return undefined;
        }
        if (!hasWorkbookMetadataForSheetRename(this.options.metadata) && sheet.styleRanges.length === 0 && sheet.formatRanges.length === 0) {
            this.options.sheetsByName.delete(oldName);
            sheet.name = trimmedName;
            this.options.sheetsByName.set(trimmedName, sheet);
            return sheet;
        }
        return this.renameExistingSheet(sheet, oldName, trimmedName);
    }
    renameExistingSheet(sheet, oldName, trimmedName) {
        this.options.sheetsByName.delete(oldName);
        sheet.name = trimmedName;
        this.options.sheetsByName.set(trimmedName, sheet);
        this.options.renameSheetRecords(oldName, trimmedName);
        if (sheet.styleRanges.length > 0) {
            sheet.styleRanges = sheet.styleRanges.map((record) => record.range.sheetName === oldName ? { ...record, range: { ...record.range, sheetName: trimmedName } } : record);
        }
        if (sheet.formatRanges.length > 0) {
            sheet.formatRanges = sheet.formatRanges.map((record) => record.range.sheetName === oldName ? { ...record, range: { ...record.range, sheetName: trimmedName } } : record);
        }
        return sheet;
    }
    getSheet(name) {
        return this.options.sheetsByName.get(name);
    }
    getSheetById(id) {
        return this.options.sheetsById.get(id);
    }
    getOrCreateSheet(name) {
        return this.getSheet(name) ?? this.createSheet(name);
    }
    getSheetNameById(id) {
        return this.options.sheetsById.get(id)?.name ?? '';
    }
    getSheetColumnVersion(sheetName, col) {
        return this.options.sheetsByName.get(sheetName)?.columnVersions[col] ?? 0;
    }
    getSheetStructureVersion(sheetName) {
        return this.options.sheetsByName.get(sheetName)?.structureVersion ?? 0;
    }
    reset() {
        this.options.sheetsByName.clear();
        this.options.sheetsById.clear();
        this.nextSheetId = 1;
    }
    bumpSheetId(id) {
        if (Number.isInteger(id) && id >= this.nextSheetId) {
            this.nextSheetId = id + 1;
        }
    }
    moveExistingSheet(sheet, order) {
        const orderedSheets = orderedSheetRecords([...this.options.sheetsByName.values()]);
        const oldSheetIndex = orderedSheets.findIndex((candidate) => candidate.id === sheet.id);
        if (oldSheetIndex === -1) {
            return;
        }
        const newSheetIndex = clampSheetOrder(order, orderedSheets.length);
        const requiresNormalization = orderedSheets.some((candidate, index) => candidate.order !== index);
        if (oldSheetIndex === newSheetIndex && !requiresNormalization) {
            return;
        }
        orderedSheets.splice(oldSheetIndex, 1);
        orderedSheets.splice(newSheetIndex, 0, sheet);
        orderedSheets.forEach((candidate, index) => {
            candidate.order = index;
        });
        if (oldSheetIndex !== newSheetIndex) {
            this.options.reorderSheetRecords({
                movedSheetName: sheet.name,
                oldSheetIndex,
                newSheetIndex,
                sheetCount: orderedSheets.length,
            });
        }
    }
}
function sheetDeletionMetadataContext(sheets, sheetName) {
    const orderedSheets = orderedSheetRecords(sheets);
    const deletedSheetIndex = orderedSheets.findIndex((sheet) => sheet.name === sheetName);
    if (deletedSheetIndex === -1) {
        return undefined;
    }
    return {
        deletedSheetIndex,
        deletedSheetId: orderedSheets[deletedSheetIndex].id,
        sheetCountBeforeDelete: orderedSheets.length,
    };
}
function orderedSheetRecords(sheets) {
    return [...sheets].toSorted((left, right) => left.order - right.order || left.id - right.id);
}
function clampSheetOrder(order, sheetCount) {
    if (sheetCount <= 0) {
        return 0;
    }
    const normalizedOrder = Number.isFinite(order) ? Math.trunc(order) : 0;
    return Math.max(0, Math.min(normalizedOrder, sheetCount - 1));
}
//# sourceMappingURL=workbook-sheet-registry-store.js.map