import { normalizeWorkbookCommandReceipt } from '@bilig/workbook';
import { normalizeWorkbookCommandDescriptor } from '@bilig/workbook/features';
export class WorkbookCommandService {
    engine;
    projection;
    commands = new Map();
    constructor(engine, projection) {
        this.engine = engine;
        this.projection = projection;
    }
    registerCommand(descriptor, handler) {
        const normalized = normalizeWorkbookCommandDescriptor(descriptor);
        const key = commandKey(normalized.featureId, normalized.id);
        if (this.commands.has(key)) {
            throw new Error(`Workbook command ${normalized.featureId}.${normalized.id} is already registered`);
        }
        const registered = Object.freeze({ descriptor: normalized, handler });
        this.commands.set(key, registered);
        return () => {
            if (this.commands.get(key) === registered) {
                this.commands.delete(key);
            }
        };
    }
    listCommandDescriptors() {
        return [...this.commands.values()].map((command) => command.descriptor);
    }
    async execute(request) {
        const command = this.commands.get(commandKey(request.featureId, request.commandId));
        if (!command) {
            throw new Error(`Workbook command ${request.featureId}.${request.commandId} is not registered`);
        }
        if (request.category !== undefined && request.category !== command.descriptor.category) {
            throw new Error(`Workbook command ${request.featureId}.${request.commandId} category ${request.category} does not match descriptor`);
        }
        const receipt = await command.handler({
            ...request,
            category: request.category ?? command.descriptor.category,
        }, {
            engine: this.engine,
            projection: this.projection,
        });
        return normalizeWorkbookCommandReceipt(receipt);
    }
    preview(request) {
        return this.execute({ ...request, mode: 'preview' });
    }
    apply(request) {
        return this.execute({ ...request, mode: 'apply' });
    }
    applyAndVerify(request) {
        return this.execute({ ...request, mode: 'applyAndVerify' });
    }
}
function commandKey(featureId, commandId) {
    return `${featureId}\u0000${commandId}`;
}
//# sourceMappingURL=workbook-command-service.js.map