"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const types_1 = require("@pnpm/types");
const archy = require("archy");
const chalk_1 = require("chalk");
const cliColumns = require("cli-columns");
const path = require("path");
const R = require("ramda");
const getPkgInfo_1 = require("./getPkgInfo");
const sortPackages = R.sortBy(R.path(['pkg', 'name']));
const DEV_DEP_ONLY_CLR = chalk_1.default.yellow;
const PROD_DEP_CLR = (s) => s; // just use the default color
const OPTIONAL_DEP_CLR = chalk_1.default.blue;
const NOT_SAVED_DEP_CLR = chalk_1.default.red;
const LEGEND = `Legend: ${PROD_DEP_CLR('production dependency')}, ${OPTIONAL_DEP_CLR('optional only')}, ${DEV_DEP_ONLY_CLR('dev only')}\n\n`;
async function default_1(project, tree, opts) {
    if (!opts.alwaysPrintRootPackage &&
        (!tree.dependencies || !tree.dependencies.length) &&
        (!tree.devDependencies || !tree.devDependencies.length) &&
        (!tree.optionalDependencies || !tree.optionalDependencies.length) &&
        (!tree.unsavedDependencies || !tree.unsavedDependencies.length))
        return '';
    let label = '';
    if (project.name) {
        label += project.name;
        if (project.version) {
            label += `@${project.version}`;
        }
        label += ' ';
    }
    label += project.path;
    let output = (opts.depth > -1 ? LEGEND : '') + label + '\n';
    const useColumns = opts.depth === 0 && opts.long === false && !opts.search;
    for (let dependenciesField of [...types_1.DEPENDENCIES_FIELDS.sort(), 'unsavedDependencies']) {
        if (tree[dependenciesField] && tree[dependenciesField].length) {
            const depsLabel = chalk_1.default.cyanBright(dependenciesField !== 'unsavedDependencies'
                ? `${dependenciesField}:`
                : 'not saved (you should add these dependencies to package.json if you need them):');
            output += `\n${depsLabel}\n`;
            if (useColumns && tree[dependenciesField].length > 10) {
                output += cliColumns(tree[dependenciesField].map(printLabel)) + '\n';
                continue;
            }
            const gPkgColor = dependenciesField === 'unsavedDependencies' ? () => NOT_SAVED_DEP_CLR : getPkgColor;
            const data = await toArchyTree(gPkgColor, tree[dependenciesField], {
                long: opts.long,
                modules: path.join(project.path, 'node_modules'),
            });
            for (const d of data) {
                output += archy(d);
            }
        }
    }
    return output.replace(/\n$/, '');
}
exports.default = default_1;
async function toArchyTree(getPkgColor, entryNodes, opts) {
    return Promise.all(sortPackages(entryNodes).map(async (node) => {
        const nodes = await toArchyTree(getPkgColor, node.dependencies || [], opts);
        if (opts.long) {
            const pkg = await getPkgInfo_1.default(node);
            const labelLines = [
                printLabel(getPkgColor, node),
                pkg.description,
            ];
            if (pkg.repository) {
                labelLines.push(pkg.repository);
            }
            if (pkg.homepage) {
                labelLines.push(pkg.homepage);
            }
            return {
                label: labelLines.join('\n'),
                nodes,
            };
        }
        return {
            label: printLabel(getPkgColor, node),
            nodes,
        };
    }));
}
exports.toArchyTree = toArchyTree;
function printLabel(getPkgColor, node) {
    let color = getPkgColor(node);
    let txt = `${color(node.name)} ${chalk_1.default.gray(node.version)}`;
    if (node.searched) {
        return chalk_1.default.bold.bgBlack(txt);
    }
    if (node.isPeer) {
        txt += ' peer';
    }
    return txt;
}
function getPkgColor(node) {
    if (node.dev === true)
        return DEV_DEP_ONLY_CLR;
    if (node.optional)
        return OPTIONAL_DEP_CLR;
    return PROD_DEP_CLR;
}
