"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const cli_utils_1 = require("@pnpm/cli-utils");
const outdated_1 = require("@pnpm/outdated");
const table_1 = require("@zkochan/table");
const outdated_2 = require("./outdated");
const utils_1 = require("./utils");
const chalk = require("chalk");
const R = require("ramda");
const DEP_PRIORITY = {
    dependencies: 1,
    devDependencies: 2,
    optionalDependencies: 0,
};
const COMPARATORS = [
    ...utils_1.DEFAULT_COMPARATORS,
    (o1, o2) => DEP_PRIORITY[o1.belongsTo] - DEP_PRIORITY[o2.belongsTo],
];
exports.default = async (pkgs, params, opts) => {
    const outdatedMap = {};
    const outdatedPackagesByProject = await outdated_1.outdatedDepsOfProjects(pkgs, params, { ...opts, fullMetadata: opts.long });
    for (let i = 0; i < outdatedPackagesByProject.length; i++) {
        const { dir, manifest } = pkgs[i];
        outdatedPackagesByProject[i].forEach((outdatedPkg) => {
            const key = JSON.stringify([outdatedPkg.packageName, outdatedPkg.current, outdatedPkg.belongsTo]);
            if (!outdatedMap[key]) {
                outdatedMap[key] = { ...outdatedPkg, dependentPkgs: [] };
            }
            outdatedMap[key].dependentPkgs.push({ location: dir, manifest });
        });
    }
    if (R.isEmpty(outdatedMap))
        return { output: '', exitCode: 0 };
    if (opts.table !== false) {
        return { output: renderOutdatedTable(outdatedMap, opts), exitCode: 1 };
    }
    return { output: renderOutdatedList(outdatedMap, opts), exitCode: 1 };
};
function renderOutdatedTable(outdatedMap, opts) {
    const columnNames = [
        'Package',
        'Current',
        'Latest',
        'Dependents',
    ];
    const columnFns = [
        outdated_2.renderPackageName,
        outdated_2.renderCurrent,
        outdated_2.renderLatest,
        dependentPackages,
    ];
    if (opts.long) {
        columnNames.push('Details');
        columnFns.push(outdated_2.renderDetails);
    }
    // Avoid the overhead of allocating a new array caused by calling `array.map()`
    for (let i = 0; i < columnNames.length; i++)
        columnNames[i] = chalk.blueBright(columnNames[i]);
    const data = [
        columnNames,
        ...sortOutdatedPackages(Object.values(outdatedMap))
            .map((outdatedPkg) => columnFns.map((fn) => fn(outdatedPkg))),
    ];
    return table_1.table(data, {
        ...cli_utils_1.TABLE_OPTIONS,
        columns: {
            ...cli_utils_1.TABLE_OPTIONS.columns,
            // Dependents column:
            3: {
                width: outdated_2.getCellWidth(data, 3, 30),
                wrapWord: true,
            },
        },
    });
}
function renderOutdatedList(outdatedMap, opts) {
    return sortOutdatedPackages(Object.values(outdatedMap))
        .map((outdatedPkg) => {
        let info = `${chalk.bold(outdated_2.renderPackageName(outdatedPkg))}
${outdated_2.renderCurrent(outdatedPkg)} ${chalk.grey('=>')} ${outdated_2.renderLatest(outdatedPkg)}`;
        const dependents = dependentPackages(outdatedPkg);
        if (dependents) {
            info += `\n${chalk.bold(outdatedPkg.dependentPkgs.length > 1
                ? 'Dependents:'
                : 'Dependent:')} ${dependents}`;
        }
        if (opts.long) {
            const details = outdated_2.renderDetails(outdatedPkg);
            if (details) {
                info += `\n${details}`;
            }
        }
        return info;
    })
        .join('\n\n') + '\n';
}
function dependentPackages({ dependentPkgs }) {
    return dependentPkgs
        .map(({ manifest, location }) => { var _a; return (_a = manifest.name) !== null && _a !== void 0 ? _a : location; })
        .sort()
        .join(', ');
}
function sortOutdatedPackages(outdatedPackages) {
    return R.sortWith(COMPARATORS, outdatedPackages.map(outdated_2.toOutdatedWithVersionDiff));
}
//# sourceMappingURL=recursive.js.map