"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("@pnpm/utils");
const getPreferredVersions_1 = require("./getPreferredVersions");
const resolveDependencies_1 = require("./resolveDependencies");
function default_1(opts) {
    return __awaiter(this, void 0, void 0, function* () {
        const directNonLinkedDepsByImporterId = {};
        const linkedDependenciesByImporterId = {};
        const ctx = {
            childrenByParentId: {},
            currentShrinkwrap: opts.currentShrinkwrap,
            defaultTag: opts.tag,
            dependenciesTree: {},
            depth: opts.depth,
            dryRun: opts.dryRun,
            engineStrict: opts.engineStrict,
            force: opts.force,
            nodeVersion: opts.nodeVersion,
            outdatedDependencies: {},
            pendingNodes: [],
            pnpmVersion: opts.pnpmVersion,
            rawNpmConfig: opts.rawNpmConfig,
            registry: opts.wantedShrinkwrap.registry,
            resolvedPackagesByPackageId: {},
            skipped: opts.skipped,
            storeController: opts.storeController,
            verifyStoreIntegrity: opts.verifyStoreIntegrity,
            virtualStoreDir: opts.virtualStoreDir,
            wantedShrinkwrap: opts.wantedShrinkwrap,
        };
        yield Promise.all(opts.importers.map((importer) => __awaiter(this, void 0, void 0, function* () {
            const shrImporter = opts.wantedShrinkwrap.importers[importer.id];
            const linkedDependencies = [];
            directNonLinkedDepsByImporterId[importer.id] = yield resolveDependencies_1.default(Object.assign({}, ctx, { linkedDependencies, preferredVersions: opts.preferredVersions || importer.pkg && getPreferredVersions_1.default(importer.pkg) || {}, prefix: importer.prefix }), importer.nonLinkedPackages, {
                currentDepth: 0,
                hasManifestInShrinkwrap: opts.hasManifestInShrinkwrap,
                keypath: [],
                localPackages: opts.localPackages,
                parentNodeId: utils_1.ROOT_NODE_ID,
                readPackageHook: opts.hooks.readPackage,
                resolvedDependencies: Object.assign({}, shrImporter.dependencies, shrImporter.devDependencies, shrImporter.optionalDependencies),
                shamefullyFlatten: importer.shamefullyFlatten,
                sideEffectsCache: opts.sideEffectsCache,
                update: opts.update,
            });
            linkedDependenciesByImporterId[importer.id] = linkedDependencies;
        })));
        ctx.pendingNodes.forEach((pendingNode) => {
            ctx.dependenciesTree[pendingNode.nodeId] = {
                children: () => buildTree(ctx, pendingNode.nodeId, pendingNode.resolvedPackage.id, ctx.childrenByParentId[pendingNode.resolvedPackage.id], pendingNode.depth + 1, pendingNode.installable),
                depth: pendingNode.depth,
                installable: pendingNode.installable,
                resolvedPackage: pendingNode.resolvedPackage,
            };
        });
        const resolvedImporters = {};
        for (const importer of opts.importers) {
            const directNonLinkedDeps = directNonLinkedDepsByImporterId[importer.id];
            const linkedDependencies = linkedDependenciesByImporterId[importer.id];
            resolvedImporters[importer.id] = {
                directDependencies: [
                    ...directNonLinkedDeps
                        .map((dependency) => (Object.assign({}, ctx.dependenciesTree[dependency.nodeId].resolvedPackage, { alias: dependency.alias, normalizedPref: dependency.normalizedPref }))),
                    ...linkedDependencies,
                ],
                directNodeIdsByAlias: directNonLinkedDeps
                    .reduce((acc, dependency) => {
                    acc[dependency.alias] = dependency.nodeId;
                    return acc;
                }, {}),
                linkedDependencies,
            };
        }
        return {
            dependenciesTree: ctx.dependenciesTree,
            outdatedDependencies: ctx.outdatedDependencies,
            resolvedImporters,
            resolvedPackagesByPackageId: ctx.resolvedPackagesByPackageId,
        };
    });
}
exports.default = default_1;
function buildTree(ctx, parentNodeId, parentId, children, depth, installable) {
    const childrenNodeIds = {};
    for (const child of children) {
        if (utils_1.nodeIdContainsSequence(parentNodeId, parentId, child.pkgId)) {
            continue;
        }
        const childNodeId = utils_1.createNodeId(parentNodeId, child.pkgId);
        childrenNodeIds[child.alias] = childNodeId;
        installable = installable && !ctx.skipped.has(child.pkgId);
        ctx.dependenciesTree[childNodeId] = {
            children: () => buildTree(ctx, childNodeId, child.pkgId, ctx.childrenByParentId[child.pkgId], depth + 1, installable),
            depth,
            installable,
            resolvedPackage: ctx.resolvedPackagesByPackageId[child.pkgId],
        };
    }
    return childrenNodeIds;
}
//# sourceMappingURL=index.js.map