"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildPlanServiceNodeFromResolvedValueElementMetadata = exports.buildPlanServiceNodeFromClassElementMetadata = void 0;
exports.plan = plan;
const buildGetPlanOptionsFromPlanParams_1 = require("../calculations/buildGetPlanOptionsFromPlanParams");
const handlePlanError_1 = require("../calculations/handlePlanError");
const LazyPlanServiceNode_1 = require("../models/LazyPlanServiceNode");
const curryBuildPlanServiceNode_1 = require("./curryBuildPlanServiceNode");
const curryBuildPlanServiceNodeFromClassElementMetadata_1 = require("./curryBuildPlanServiceNodeFromClassElementMetadata");
const curryBuildPlanServiceNodeFromResolvedValueElementMetadata_1 = require("./curryBuildPlanServiceNodeFromResolvedValueElementMetadata");
const curryBuildServiceNodeBindings_1 = require("./curryBuildServiceNodeBindings");
const currySubplan_1 = require("./currySubplan");
class LazyRootPlanServiceNode extends LazyPlanServiceNode_1.LazyPlanServiceNode {
    #params;
    constructor(params, serviceNode) {
        super(serviceNode, serviceNode.serviceIdentifier);
        this.#params = params;
    }
    _buildPlanServiceNode() {
        return buildPlanServiceNode(this.#params);
    }
}
exports.buildPlanServiceNodeFromClassElementMetadata = (0, curryBuildPlanServiceNodeFromClassElementMetadata_1.curryBuildPlanServiceNodeFromClassElementMetadata)(circularBuildServiceNodeBindings);
exports.buildPlanServiceNodeFromResolvedValueElementMetadata = (0, curryBuildPlanServiceNodeFromResolvedValueElementMetadata_1.curryBuildPlanServiceNodeFromResolvedValueElementMetadata)(circularBuildServiceNodeBindings);
const subplan = (0, currySubplan_1.currySubplan)(exports.buildPlanServiceNodeFromClassElementMetadata, exports.buildPlanServiceNodeFromResolvedValueElementMetadata, exports.buildPlanServiceNodeFromClassElementMetadata, exports.buildPlanServiceNodeFromResolvedValueElementMetadata);
const buildServiceNodeBindings = (0, curryBuildServiceNodeBindings_1.curryBuildServiceNodeBindings)(subplan);
function circularBuildServiceNodeBindings(params, bindingConstraintsList, serviceBindings, parentNode, chainedBindings) {
    return buildServiceNodeBindings(params, bindingConstraintsList, serviceBindings, parentNode, chainedBindings);
}
const buildPlanServiceNode = (0, curryBuildPlanServiceNode_1.curryBuildPlanServiceNode)(buildServiceNodeBindings);
function plan(params) {
    try {
        const getPlanOptions = (0, buildGetPlanOptionsFromPlanParams_1.buildGetPlanOptionsFromPlanParams)(params);
        const planResultFromCache = params.operations.getPlan(getPlanOptions);
        if (planResultFromCache !== undefined) {
            return planResultFromCache;
        }
        const serviceNode = buildPlanServiceNode(params);
        const planResult = {
            tree: {
                root: new LazyRootPlanServiceNode(params, serviceNode),
            },
        };
        // Set the plan result in the cache no matter what, even if the plan is context dependent
        params.operations.setPlan(getPlanOptions, planResult);
        return planResult;
    }
    catch (error) {
        (0, handlePlanError_1.handlePlanError)(params, error);
    }
}
//# sourceMappingURL=plan.js.map