"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.currySubplan = currySubplan;
const ClassElementMetadataKind_1 = require("../../metadata/models/ClassElementMetadataKind");
const ResolvedValueElementMetadataKind_1 = require("../../metadata/models/ResolvedValueElementMetadataKind");
const getServiceFromMaybeLazyServiceIdentifier_1 = require("../calculations/getServiceFromMaybeLazyServiceIdentifier");
const isInstanceBindingNode_1 = require("../calculations/isInstanceBindingNode");
const tryBuildGetPlanOptionsFromManagedClassElementMetadata_1 = require("../calculations/tryBuildGetPlanOptionsFromManagedClassElementMetadata");
const tryBuildGetPlanOptionsFromResolvedValueElementMetadata_1 = require("../calculations/tryBuildGetPlanOptionsFromResolvedValueElementMetadata");
const LazyPlanServiceNode_1 = require("../models/LazyPlanServiceNode");
const cacheNonRootPlanServiceNode_1 = require("./cacheNonRootPlanServiceNode");
class LazyManagedClassMetadataPlanServiceNode extends LazyPlanServiceNode_1.LazyPlanServiceNode {
    #params;
    #buildLazyPlanServiceNodeNodeFromClassElementMetadata;
    #bindingConstraintsList;
    #elementMetadata;
    constructor(params, buildLazyPlanServiceNodeNodeFromClassElementMetadata, bindingConstraintsList, elementMetadata, serviceNode) {
        super(serviceNode, (0, getServiceFromMaybeLazyServiceIdentifier_1.getServiceFromMaybeLazyServiceIdentifier)(elementMetadata.value));
        this.#buildLazyPlanServiceNodeNodeFromClassElementMetadata =
            buildLazyPlanServiceNodeNodeFromClassElementMetadata;
        this.#params = params;
        this.#bindingConstraintsList = bindingConstraintsList;
        this.#elementMetadata = elementMetadata;
    }
    _buildPlanServiceNode() {
        return this.#buildLazyPlanServiceNodeNodeFromClassElementMetadata(this.#params, this.#bindingConstraintsList, this.#elementMetadata);
    }
}
class LazyResolvedValueMetadataPlanServiceNode extends LazyPlanServiceNode_1.LazyPlanServiceNode {
    #params;
    #buildLazyPlanServiceNodeNodeFromResolvedValueElementMetadata;
    #bindingConstraintsList;
    #resolvedValueElementMetadata;
    constructor(params, buildLazyPlanServiceNodeNodeFromResolvedValueElementMetadata, bindingConstraintsList, resolvedValueElementMetadata, serviceNode) {
        super(serviceNode, (0, getServiceFromMaybeLazyServiceIdentifier_1.getServiceFromMaybeLazyServiceIdentifier)(resolvedValueElementMetadata.value));
        this.#params = params;
        this.#buildLazyPlanServiceNodeNodeFromResolvedValueElementMetadata =
            buildLazyPlanServiceNodeNodeFromResolvedValueElementMetadata;
        this.#bindingConstraintsList = bindingConstraintsList;
        this.#resolvedValueElementMetadata = resolvedValueElementMetadata;
    }
    _buildPlanServiceNode() {
        return this.#buildLazyPlanServiceNodeNodeFromResolvedValueElementMetadata(this.#params, this.#bindingConstraintsList, this.#resolvedValueElementMetadata);
    }
}
function currySubplan(buildLazyPlanServiceNodeNodeFromClassElementMetadata, buildLazyPlanServiceNodeNodeFromResolvedValueElementMetadata, buildPlanServiceNodeFromClassElementMetadata, buildPlanServiceNodeFromResolvedValueElementMetadata) {
    const subplanInstanceBindingNode = currySubplanInstanceBindingNode(buildLazyPlanServiceNodeNodeFromClassElementMetadata, buildPlanServiceNodeFromClassElementMetadata);
    const subplanResolvedValueBindingNode = currySubplanResolvedValueBindingNode(buildLazyPlanServiceNodeNodeFromResolvedValueElementMetadata, buildPlanServiceNodeFromResolvedValueElementMetadata);
    return (params, bindingConstraintsList) => {
        if ((0, isInstanceBindingNode_1.isInstanceBindingNode)(params.node)) {
            return subplanInstanceBindingNode(params, params.node, bindingConstraintsList);
        }
        else {
            return subplanResolvedValueBindingNode(params, params.node, bindingConstraintsList);
        }
    };
}
function currySubplanInstanceBindingNode(buildLazyPlanServiceNodeNodeFromClassElementMetadata, buildPlanServiceNodeFromClassElementMetadata) {
    const handlePlanServiceNodeBuildFromClassElementMetadata = curryHandlePlanServiceNodeBuildFromClassElementMetadata(buildLazyPlanServiceNodeNodeFromClassElementMetadata, buildPlanServiceNodeFromClassElementMetadata);
    return (params, node, bindingConstraintsList) => {
        const classMetadata = node.classMetadata;
        for (const [index, elementMetadata,] of classMetadata.constructorArguments.entries()) {
            node.constructorParams[index] =
                handlePlanServiceNodeBuildFromClassElementMetadata(params, bindingConstraintsList, elementMetadata);
        }
        for (const [propertyKey, elementMetadata] of classMetadata.properties) {
            const planServiceNode = handlePlanServiceNodeBuildFromClassElementMetadata(params, bindingConstraintsList, elementMetadata);
            if (planServiceNode !== undefined) {
                node.propertyParams.set(propertyKey, planServiceNode);
            }
        }
        return params.node;
    };
}
function currySubplanResolvedValueBindingNode(buildLazyPlanServiceNodeNodeFromResolvedValueElementMetadata, buildPlanServiceNodeFromResolvedValueElementMetadata) {
    const handlePlanServiceNodeBuildFromResolvedValueElementMetadata = curryHandlePlanServiceNodeBuildFromResolvedValueElementMetadata(buildLazyPlanServiceNodeNodeFromResolvedValueElementMetadata, buildPlanServiceNodeFromResolvedValueElementMetadata);
    return (params, node, bindingConstraintsList) => {
        const resolvedValueMetadata = node.binding.metadata;
        for (const [index, elementMetadata,] of resolvedValueMetadata.arguments.entries()) {
            node.params[index] =
                handlePlanServiceNodeBuildFromResolvedValueElementMetadata(params, bindingConstraintsList, elementMetadata);
        }
        return params.node;
    };
}
function curryHandlePlanServiceNodeBuildFromClassElementMetadata(buildLazyPlanServiceNodeNodeFromClassElementMetadata, buildPlanServiceNodeFromClassElementMetadata) {
    return (params, bindingConstraintsList, elementMetadata) => {
        if (elementMetadata.kind === ClassElementMetadataKind_1.ClassElementMetadataKind.unmanaged) {
            return undefined;
        }
        const getPlanOptions = (0, tryBuildGetPlanOptionsFromManagedClassElementMetadata_1.tryBuildGetPlanOptionsFromManagedClassElementMetadata)(elementMetadata);
        if (getPlanOptions !== undefined) {
            const planResult = params.operations.getPlan(getPlanOptions);
            if (planResult !== undefined && planResult.tree.root.isContextFree) {
                return planResult.tree.root;
            }
        }
        const serviceNode = buildPlanServiceNodeFromClassElementMetadata(params, bindingConstraintsList, elementMetadata);
        const lazyPlanServiceNode = new LazyManagedClassMetadataPlanServiceNode(params, buildLazyPlanServiceNodeNodeFromClassElementMetadata, bindingConstraintsList, elementMetadata, serviceNode);
        (0, cacheNonRootPlanServiceNode_1.cacheNonRootPlanServiceNode)(getPlanOptions, params.operations, lazyPlanServiceNode, {
            bindingConstraintsList,
            chainedBindings: elementMetadata.kind === ClassElementMetadataKind_1.ClassElementMetadataKind.multipleInjection &&
                elementMetadata.chained,
            optionalBindings: elementMetadata.optional,
        });
        return lazyPlanServiceNode;
    };
}
function curryHandlePlanServiceNodeBuildFromResolvedValueElementMetadata(buildLazyPlanServiceNodeNodeFromResolvedValueElementMetadata, buildPlanServiceNodeFromResolvedValueElementMetadata) {
    return (params, bindingConstraintsList, elementMetadata) => {
        const getPlanOptions = (0, tryBuildGetPlanOptionsFromResolvedValueElementMetadata_1.tryBuildGetPlanOptionsFromResolvedValueElementMetadata)(elementMetadata);
        if (getPlanOptions !== undefined) {
            const planResult = params.operations.getPlan(getPlanOptions);
            if (planResult !== undefined && planResult.tree.root.isContextFree) {
                return planResult.tree.root;
            }
        }
        const serviceNode = buildPlanServiceNodeFromResolvedValueElementMetadata(params, bindingConstraintsList, elementMetadata);
        const lazyPlanServiceNode = new LazyResolvedValueMetadataPlanServiceNode(params, buildLazyPlanServiceNodeNodeFromResolvedValueElementMetadata, bindingConstraintsList, elementMetadata, serviceNode);
        (0, cacheNonRootPlanServiceNode_1.cacheNonRootPlanServiceNode)(getPlanOptions, params.operations, lazyPlanServiceNode, {
            bindingConstraintsList,
            chainedBindings: elementMetadata.kind ===
                ResolvedValueElementMetadataKind_1.ResolvedValueElementMetadataKind.multipleInjection &&
                elementMetadata.chained,
            optionalBindings: elementMetadata.optional,
        });
        return lazyPlanServiceNode;
    };
}
//# sourceMappingURL=currySubplan.js.map