"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolve = resolve;
const common_1 = require("@inversifyjs/common");
const BindingType_1 = require("../../binding/models/BindingType");
const InversifyCoreError_1 = require("../../error/models/InversifyCoreError");
const InversifyCoreErrorKind_1 = require("../../error/models/InversifyCoreErrorKind");
const handleResolveError_1 = require("../../planning/calculations/handleResolveError");
const isPlanServiceRedirectionBindingNode_1 = require("../../planning/calculations/isPlanServiceRedirectionBindingNode");
const resolveConstantValueBinding_1 = require("./resolveConstantValueBinding");
const resolveDynamicValueBinding_1 = require("./resolveDynamicValueBinding");
const resolveFactoryBinding_1 = require("./resolveFactoryBinding");
const resolveInstanceBindingConstructorParams_1 = require("./resolveInstanceBindingConstructorParams");
const resolveInstanceBindingNode_1 = require("./resolveInstanceBindingNode");
const resolveInstanceBindingNodeAsyncFromConstructorParams_1 = require("./resolveInstanceBindingNodeAsyncFromConstructorParams");
const resolveInstanceBindingNodeFromConstructorParams_1 = require("./resolveInstanceBindingNodeFromConstructorParams");
const resolveProviderBinding_1 = require("./resolveProviderBinding");
const resolveResolvedValueBindingNode_1 = require("./resolveResolvedValueBindingNode");
const resolveResolvedValueBindingParams_1 = require("./resolveResolvedValueBindingParams");
const resolveScopedInstanceBindingNode_1 = require("./resolveScopedInstanceBindingNode");
const resolveScopedResolvedValueBindingNode_1 = require("./resolveScopedResolvedValueBindingNode");
const resolveServiceRedirectionBindingNode_1 = require("./resolveServiceRedirectionBindingNode");
const setInstanceProperties_1 = require("./setInstanceProperties");
const setInstanceProperties = (0, setInstanceProperties_1.setInstanceProperties)(resolveServiceNode);
const resolveServiceRedirectionBindingNode = (0, resolveServiceRedirectionBindingNode_1.resolveServiceRedirectionBindingNode)(resolveBindingNode);
const resolveInstanceBindingNode = (0, resolveInstanceBindingNode_1.resolveInstanceBindingNode)(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(0, resolveInstanceBindingConstructorParams_1.resolveInstanceBindingConstructorParams)(resolveServiceNode), (0, resolveInstanceBindingNodeAsyncFromConstructorParams_1.resolveInstanceBindingNodeAsyncFromConstructorParams)((0, resolveInstanceBindingNodeFromConstructorParams_1.resolveInstanceBindingNodeFromConstructorParams)(setInstanceProperties)), (0, resolveInstanceBindingNodeFromConstructorParams_1.resolveInstanceBindingNodeFromConstructorParams)(setInstanceProperties));
const resolveResolvedValueBindingNode = (0, resolveResolvedValueBindingNode_1.resolveResolvedValueBindingNode)(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(0, resolveResolvedValueBindingParams_1.resolveResolvedValueBindingParams)(resolveServiceNode));
const resolveScopedInstanceBindingNode = (0, resolveScopedInstanceBindingNode_1.resolveScopedInstanceBindingNode)(resolveInstanceBindingNode);
const resolveScopedResolvedValueBindingNode = (0, resolveScopedResolvedValueBindingNode_1.resolveScopedResolvedValueBindingNode)(resolveResolvedValueBindingNode);
function resolve(params) {
    try {
        const serviceNode = params.planResult.tree.root;
        return resolveServiceNode(params, serviceNode);
    }
    catch (error) {
        (0, handleResolveError_1.handleResolveError)(params, error);
    }
}
function resolveBindingNode(params, planBindingNode) {
    switch (planBindingNode.binding.type) {
        case BindingType_1.bindingTypeValues.ConstantValue:
            return (0, resolveConstantValueBinding_1.resolveConstantValueBinding)(params, planBindingNode.binding);
        case BindingType_1.bindingTypeValues.DynamicValue:
            return (0, resolveDynamicValueBinding_1.resolveDynamicValueBinding)(params, planBindingNode.binding);
        case BindingType_1.bindingTypeValues.Factory:
            return (0, resolveFactoryBinding_1.resolveFactoryBinding)(params, planBindingNode.binding);
        case BindingType_1.bindingTypeValues.Instance:
            return resolveScopedInstanceBindingNode(params, planBindingNode);
        case BindingType_1.bindingTypeValues.Provider:
            return (0, resolveProviderBinding_1.resolveProviderBinding)(params, planBindingNode.binding);
        case BindingType_1.bindingTypeValues.ResolvedValue:
            return resolveScopedResolvedValueBindingNode(params, planBindingNode);
    }
}
function resolveServiceNode(params, serviceNode) {
    if (serviceNode.bindings === undefined) {
        return undefined;
    }
    if (Array.isArray(serviceNode.bindings)) {
        return resolveMultipleBindingServiceNode(params, serviceNode.bindings);
    }
    return resolveSingleBindingServiceNode(params, serviceNode.bindings);
}
function resolveMultipleBindingServiceNode(params, bindings) {
    const resolvedValues = [];
    for (const binding of bindings) {
        if ((0, isPlanServiceRedirectionBindingNode_1.isPlanServiceRedirectionBindingNode)(binding)) {
            resolvedValues.push(...resolveServiceRedirectionBindingNode(params, binding));
        }
        else {
            resolvedValues.push(resolveBindingNode(params, binding));
        }
    }
    if (resolvedValues.some(common_1.isPromise)) {
        return Promise.all(resolvedValues);
    }
    return resolvedValues;
}
function resolveSingleBindingServiceNode(params, binding) {
    if ((0, isPlanServiceRedirectionBindingNode_1.isPlanServiceRedirectionBindingNode)(binding)) {
        const resolvedValues = resolveServiceRedirectionBindingNode(params, binding);
        if (resolvedValues.length === 1) {
            return resolvedValues[0];
        }
        else {
            throw new InversifyCoreError_1.InversifyCoreError(InversifyCoreErrorKind_1.InversifyCoreErrorKind.resolution, 'Unexpected multiple resolved values on single injection');
        }
    }
    else {
        return resolveBindingNode(params, binding);
    }
}
//# sourceMappingURL=resolve.js.map