"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CommandBusBase = void 0;
const constants_1 = require("./constants");
const invalidCommandHandler_exception_1 = require("./exceptions/invalidCommandHandler.exception");
const helpers_1 = require("./helpers");
const commandBusOptions_1 = require("./models/commandBusOptions");
class CommandBusBase {
    constructor(options) {
        this.handlers = new Map();
        const parsedOptions = new commandBusOptions_1.CommandBusOptions(Object.assign(Object.assign({}, (Reflect.getMetadata(constants_1.COMMAND_BUS_OPTIONS, this.constructor) || {})), (options || {})));
        this.onExecute = parsedOptions.onExecute;
        this.injectionResolver = parsedOptions.injectionResolver;
        this.name = parsedOptions.name;
    }
    bindHandler(handler, commandName, handlerInstance) {
        this.handlers.set(commandName, [handler, handlerInstance]);
    }
    registerHandlerInstance(handlerInstance) {
        const handler = handlerInstance;
        const constructor = (0, helpers_1.getConstructor)(handler);
        const target = Reflect.getMetadata(constants_1.COMMAND_HANDLER_METADATA, (0, helpers_1.getConstructor)(handlerInstance));
        if (!target) {
            throw new invalidCommandHandler_exception_1.InvalidQueueHandlerException(constructor.name, this.name);
        }
        if (target.bus !== Object.getPrototypeOf(this).constructor) {
            return;
        }
        this.bindHandler(handler.execute, target.data.name, handler);
    }
    registerHandlersInstances(handlersInstances = []) {
        handlersInstances.forEach((handler) => this.registerHandlerInstance(handler));
    }
    registerHandlerFactory(Handler, injectionResolver) {
        const resolver = injectionResolver || this.injectionResolver;
        if (!resolver) {
            throw new Error('injectionResolver is required');
        }
        return this.registerHandlerInstance(injectionResolver(Handler));
    }
    registerHandlersFactories(handlersFactories = [], injectionResolver) {
        handlersFactories.forEach((handlerFactory) => this.registerHandlerFactory(handlerFactory, injectionResolver));
    }
    registerFunctionHandler(command, handler) {
        this.bindHandler(handler, command.name);
    }
    registerFunctionHandlers(handlers) {
        for (const [command, handler] of handlers) {
            this.registerFunctionHandler(command, handler);
        }
    }
    execute(command, options) {
        const commandName = command.constructor.name;
        return this.executeByName(commandName, command, options);
    }
    executeByName(commandName, data, options) {
        const [handler, instance] = this.handlers.get(commandName);
        if (!handler) {
            throw new invalidCommandHandler_exception_1.InvalidQueueHandlerException(commandName);
        }
        if (this.onExecute) {
            return this.onExecute(data, { handler, name: commandName, options, instance });
        }
        return handler(data, options);
    }
}
exports.CommandBusBase = CommandBusBase;
//# sourceMappingURL=commandBusBase.js.map