"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.curryBuildServiceNodeBindings = curryBuildServiceNodeBindings;
const BindingConstraintsImplementation_1 = require("../../binding/models/BindingConstraintsImplementation");
const BindingType_1 = require("../../binding/models/BindingType");
const buildFilteredServiceBindings_1 = require("../calculations/buildFilteredServiceBindings");
const isPlanServiceRedirectionBindingNode_1 = require("../calculations/isPlanServiceRedirectionBindingNode");
function curryBuildServiceNodeBindings(subplan) {
    const buildInstancePlanBindingNode = curryBuildInstancePlanBindingNode(subplan);
    const buildResolvedValuePlanBindingNode = curryBuildResolvedValuePlanBindingNode(subplan);
    const buildServiceNodeBindings = (params, bindingConstraintsList, serviceBindings, parentNode, chainedBindings) => {
        const serviceIdentifier = (0, isPlanServiceRedirectionBindingNode_1.isPlanServiceRedirectionBindingNode)(parentNode)
            ? parentNode.binding.targetServiceIdentifier
            : parentNode.serviceIdentifier;
        params.servicesBranch.push(serviceIdentifier);
        const planBindingNodes = [];
        for (const binding of serviceBindings) {
            switch (binding.type) {
                case BindingType_1.bindingTypeValues.Instance: {
                    planBindingNodes.push(buildInstancePlanBindingNode(params, binding, bindingConstraintsList));
                    break;
                }
                case BindingType_1.bindingTypeValues.ResolvedValue: {
                    planBindingNodes.push(buildResolvedValuePlanBindingNode(params, binding, bindingConstraintsList));
                    break;
                }
                case BindingType_1.bindingTypeValues.ServiceRedirection: {
                    const planBindingNode = buildServiceRedirectionPlanBindingNode(params, bindingConstraintsList, binding, chainedBindings);
                    planBindingNodes.push(planBindingNode);
                    break;
                }
                default:
                    planBindingNodes.push({
                        binding: binding,
                    });
            }
        }
        params.servicesBranch.pop();
        return planBindingNodes;
    };
    const buildServiceRedirectionPlanBindingNode = curryBuildServiceRedirectionPlanBindingNode(buildServiceNodeBindings);
    return buildServiceNodeBindings;
}
function curryBuildInstancePlanBindingNode(subplan) {
    return (params, binding, bindingConstraintsList) => {
        const classMetadata = params.operations.getClassMetadata(binding.implementationType);
        const childNode = {
            binding: binding,
            classMetadata,
            constructorParams: [],
            propertyParams: new Map(),
        };
        const subplanParams = {
            autobindOptions: params.autobindOptions,
            node: childNode,
            operations: params.operations,
            servicesBranch: params.servicesBranch,
        };
        return subplan(subplanParams, bindingConstraintsList);
    };
}
function curryBuildResolvedValuePlanBindingNode(subplan) {
    return (params, binding, bindingConstraintsList) => {
        const childNode = {
            binding: binding,
            params: [],
        };
        const subplanParams = {
            autobindOptions: params.autobindOptions,
            node: childNode,
            operations: params.operations,
            servicesBranch: params.servicesBranch,
        };
        return subplan(subplanParams, bindingConstraintsList);
    };
}
function curryBuildServiceRedirectionPlanBindingNode(buildServiceNodeBindings) {
    return (params, bindingConstraintsList, binding, chainedBindings) => {
        const childNode = {
            binding,
            redirections: [],
        };
        const bindingConstraints = new BindingConstraintsImplementation_1.BindingConstraintsImplementation(bindingConstraintsList.last);
        const filteredServiceBindings = (0, buildFilteredServiceBindings_1.buildFilteredServiceBindings)(params, bindingConstraints, {
            chained: chainedBindings,
            customServiceIdentifier: binding.targetServiceIdentifier,
        });
        childNode.redirections.push(...buildServiceNodeBindings(params, bindingConstraintsList, filteredServiceBindings, childNode, chainedBindings));
        return childNode;
    };
}
//# sourceMappingURL=curryBuildServiceNodeBindings.js.map