"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CommandRegistry = void 0;
exports.getManagerMetadata = getManagerMetadata;
exports.setManagerNamespace = setManagerNamespace;
exports.addCommandHandler = addCommandHandler;
require("reflect-metadata");
const tsyringe_1 = require("tsyringe");
const PermissionRegistry_1 = require("./PermissionRegistry");
let CommandRegistry = class CommandRegistry {
    permissionRegistry;
    handlers = new Map();
    constructor(permissionRegistry) {
        this.permissionRegistry = permissionRegistry;
    }
    /**
     * Register a command handler under a namespace
     * @param namespace - The namespace (e.g., "app", "view")
     * @param command - The command name (e.g., "launch", "update-bounds")
     * @param handler - The handler function
     * @param target - The instance that owns the handler (for proper `this` binding)
     * @param methodName - The original method name for metadata lookup
     */
    register(namespace, command, handler, target, methodName) {
        const fullCommand = `${namespace}/${command}`;
        if (this.handlers.has(fullCommand)) {
            console.warn(`Command handler for "${fullCommand}" is being overwritten`);
        }
        // Look up permission from decorator metadata
        let permission;
        if (methodName && target) {
            const handlerPermission = Reflect.getMetadata("eden:handler:permission", target.constructor.prototype, methodName);
            if (handlerPermission) {
                permission = `${namespace}/${handlerPermission}`;
            }
        }
        this.handlers.set(fullCommand, {
            namespace,
            command,
            handler,
            target,
            permission,
            methodName: methodName || "",
        });
        const permStr = permission ? ` (requires: ${permission})` : "";
        console.log(`Registered command handler: ${fullCommand}${permStr}`);
    }
    /**
     * Register multiple handlers from a manager instance
     * @param manager - The manager instance to register handlers from
     */
    registerManager(manager) {
        const metadata = getManagerMetadata(manager);
        if (!metadata) {
            console.warn("Manager has no command handlers to register");
            return;
        }
        const { namespace, handlers } = metadata;
        for (const [command, methodName] of handlers.entries()) {
            const handler = manager[methodName];
            if (typeof handler === "function") {
                this.register(namespace, command, handler.bind(manager), manager, methodName);
            }
        }
    }
    /**
     * Execute a command by its full name
     * @param fullCommand - The full command name (e.g., "process/launch")
     * @param args - The command arguments
     * @param appId - Optional app ID for permission checking
     * @returns The command result
     */
    async execute(fullCommand, args, appId) {
        const metadata = this.handlers.get(fullCommand);
        if (!metadata) {
            throw new Error(`Unknown command: ${fullCommand}`);
        }
        // Check permission if required
        if (metadata.permission && appId && this.permissionRegistry) {
            if (!this.permissionRegistry.hasPermission(appId, metadata.permission)) {
                throw new Error(`Permission denied: ${metadata.permission} required for ${fullCommand}`);
            }
        }
        try {
            return await metadata.handler.call(metadata.target, args);
        }
        catch (error) {
            console.error(`Error executing command ${fullCommand}:`, error);
            throw error;
        }
    }
    /**
     * Check if a command is registered
     */
    has(fullCommand) {
        return this.handlers.has(fullCommand);
    }
    /**
     * Get all registered command names
     */
    getCommands() {
        return Array.from(this.handlers.keys());
    }
    /**
     * Get commands for a specific namespace
     */
    getNamespaceCommands(namespace) {
        return Array.from(this.handlers.values())
            .filter((meta) => meta.namespace === namespace)
            .map((meta) => `${meta.namespace}/${meta.command}`);
    }
    /**
     * Clear all handlers (useful for testing)
     */
    clear() {
        this.handlers.clear();
    }
};
exports.CommandRegistry = CommandRegistry;
exports.CommandRegistry = CommandRegistry = __decorate([
    (0, tsyringe_1.singleton)(),
    (0, tsyringe_1.injectable)(),
    __param(0, (0, tsyringe_1.inject)(PermissionRegistry_1.PermissionRegistry)),
    __metadata("design:paramtypes", [PermissionRegistry_1.PermissionRegistry])
], CommandRegistry);
/**
 * Metadata storage for manager namespaces and handlers
 */
const MANAGER_METADATA = new Map();
/**
 * Get manager metadata (namespace and handlers)
 */
function getManagerMetadata(instance) {
    return MANAGER_METADATA.get(instance.constructor);
}
/**
 * Set manager namespace
 */
function setManagerNamespace(target, namespace) {
    if (!MANAGER_METADATA.has(target)) {
        MANAGER_METADATA.set(target, {
            namespace,
            handlers: new Map(),
        });
    }
    else {
        MANAGER_METADATA.get(target).namespace = namespace;
    }
}
/**
 * Add command handler to manager metadata
 */
function addCommandHandler(target, command, methodName) {
    if (!MANAGER_METADATA.has(target)) {
        MANAGER_METADATA.set(target, {
            namespace: "",
            handlers: new Map(),
        });
    }
    const metadata = MANAGER_METADATA.get(target);
    metadata.handlers.set(command, methodName);
}
//# sourceMappingURL=CommandRegistry.js.map