"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.handlePlanError = handlePlanError;
const common_1 = require("@inversifyjs/common");
const isStackOverflowError_1 = require("../../error/calculations/isStackOverflowError");
const InversifyCoreError_1 = require("../../error/models/InversifyCoreError");
const InversifyCoreErrorKind_1 = require("../../error/models/InversifyCoreErrorKind");
/**
 * Extracts a likely circular dependency asuming a service asociated to a
 * service identifier should not be asociated to services asociated to the same
 * service identifier.
 *
 * Important note: given the current binding constraints, there's no way to know
 * which is exactly the circular dependency. Custom ancestor based constraints might
 * allow circular dependencies breaking the loop when a certain condition is met.
 *
 * @param params plan params
 */
function extractLikelyCircularDependency(params) {
    const serviceIdentifiers = new Set();
    for (const serviceIdentifier of params.servicesBranch) {
        if (serviceIdentifiers.has(serviceIdentifier)) {
            return [...serviceIdentifiers, serviceIdentifier];
        }
        serviceIdentifiers.add(serviceIdentifier);
    }
    return [...serviceIdentifiers];
}
function handlePlanError(params, error) {
    if ((0, isStackOverflowError_1.isStackOverflowError)(error)) {
        const stringifiedCircularDependencies = stringifyServiceIdentifierTrace(extractLikelyCircularDependency(params));
        throw new InversifyCoreError_1.InversifyCoreError(InversifyCoreErrorKind_1.InversifyCoreErrorKind.planning, `Circular dependency found: ${stringifiedCircularDependencies}`, { cause: error });
    }
    throw error;
}
function stringifyServiceIdentifierTrace(serviceIdentifiers) {
    const serviceIdentifiersArray = [...serviceIdentifiers];
    if (serviceIdentifiersArray.length === 0) {
        return '(No dependency trace)';
    }
    return serviceIdentifiersArray.map(common_1.stringifyServiceIdentifier).join(' -> ');
}
//# sourceMappingURL=handlePlanError.js.map