"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const R = require("ramda");
const pnpm_logger_1 = require("pnpm-logger");
const SHRINKWRAP_VERSION = 3;
function prune(shr, pkg) {
    const packages = {};
    const optionalDependencies = R.keys(pkg.optionalDependencies);
    const dependencies = R.difference(R.keys(pkg.dependencies), optionalDependencies);
    const devDependencies = R.difference(R.difference(R.keys(pkg.devDependencies), optionalDependencies), dependencies);
    const allDeps = R.reduce(R.union, [], [optionalDependencies, devDependencies, dependencies]);
    const specifiers = {};
    const shrDependencies = {};
    const shrOptionalDependencies = {};
    const shrDevDependencies = {};
    const nonOptional = new Set();
    R.keys(shr.specifiers).forEach(depName => {
        if (allDeps.indexOf(depName) === -1)
            return;
        specifiers[depName] = shr.specifiers[depName];
        if (shr.dependencies[depName]) {
            shrDependencies[depName] = shr.dependencies[depName];
        }
        else if (shr.optionalDependencies && shr.optionalDependencies[depName]) {
            shrOptionalDependencies[depName] = shr.optionalDependencies[depName];
        }
        else if (shr.devDependencies && shr.devDependencies[depName]) {
            shrDevDependencies[depName] = shr.devDependencies[depName];
        }
    });
    if (shrOptionalDependencies) {
        let optionalPkgIds = R.keys(shrOptionalDependencies)
            .map((pkgName) => getPkgShortId(shrOptionalDependencies[pkgName], pkgName));
        copyDependencySubTree(packages, optionalPkgIds, shr, [], { registry: shr.registry, nonOptional, optional: true });
    }
    if (shrDevDependencies) {
        let devPkgIds = R.keys(shrDevDependencies)
            .map((pkgName) => getPkgShortId(shrDevDependencies[pkgName], pkgName));
        copyDependencySubTree(packages, devPkgIds, shr, [], { registry: shr.registry, nonOptional, dev: true });
    }
    let pkgIds = R.keys(shrDependencies)
        .map((pkgName) => getPkgShortId(shrDependencies[pkgName], pkgName));
    copyDependencySubTree(packages, pkgIds, shr, [], {
        registry: shr.registry,
        nonOptional,
    });
    const result = {
        version: SHRINKWRAP_VERSION,
        specifiers,
        registry: shr.registry,
        dependencies: shrDependencies,
        optionalDependencies: shrOptionalDependencies,
        devDependencies: shrDevDependencies,
        packages,
    };
    if (R.isEmpty(result.optionalDependencies)) {
        delete result.optionalDependencies;
    }
    if (R.isEmpty(result.devDependencies)) {
        delete result.devDependencies;
    }
    return result;
}
exports.default = prune;
function copyDependencySubTree(resolvedPackages, pkgIds, shr, keypath, opts) {
    for (let pkgId of pkgIds) {
        if (keypath.indexOf(pkgId) !== -1)
            continue;
        if (!shr.packages[pkgId]) {
            pnpm_logger_1.default.warn(`Cannot find resolution of ${pkgId} in shrinkwrap file`);
            continue;
        }
        const depShr = shr.packages[pkgId];
        resolvedPackages[pkgId] = depShr;
        if (opts.optional && !opts.nonOptional.has(pkgId)) {
            depShr.optional = true;
        }
        else {
            opts.nonOptional.add(pkgId);
            delete depShr.optional;
        }
        if (opts.dev) {
            depShr.dev = true;
        }
        else {
            delete depShr.dev;
        }
        const newDependencies = R.keys(depShr.dependencies)
            .map((pkgName) => getPkgShortId((depShr.dependencies && depShr.dependencies[pkgName]), pkgName));
        const newKeypath = keypath.concat([pkgId]);
        copyDependencySubTree(resolvedPackages, newDependencies, shr, newKeypath, opts);
        const newOptionalDependencies = R.keys(depShr.optionalDependencies)
            .map((pkgName) => getPkgShortId((depShr.optionalDependencies && depShr.optionalDependencies[pkgName]), pkgName));
        copyDependencySubTree(resolvedPackages, newOptionalDependencies, shr, newKeypath, Object.assign({}, opts, { optional: true }));
    }
}
function getPkgShortId(reference, pkgName) {
    if (reference.indexOf('/') === -1) {
        return `/${pkgName}/${reference}`;
    }
    return reference;
}
exports.getPkgShortId = getPkgShortId;
//# sourceMappingURL=prune.js.map