"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NodeModulesDependenciesBuilder = void 0;
const path = require("path");
const constants_1 = require("../../constants");
const _ = require("lodash");
const yok_1 = require("../../common/yok");
class NodeModulesDependenciesBuilder {
    constructor($fs) {
        this.$fs = $fs;
    }
    getProductionDependencies(projectPath, ignore) {
        const projectPackageJsonPath = path.join(projectPath, constants_1.PACKAGE_JSON_FILE_NAME);
        const packageJsonContent = this.$fs.readJson(projectPackageJsonPath);
        const dependencies = packageJsonContent && packageJsonContent.dependencies;
        const resolvedDependencies = [];
        const queue = _.keys(dependencies).map((dependencyName) => ({
            parent: null,
            parentDir: projectPath,
            name: dependencyName,
            depth: 0,
        }));
        while (queue.length) {
            const currentModule = queue.shift();
            const resolvedDependency = this.findModule(currentModule, resolvedDependencies);
            if (resolvedDependency &&
                !_.some(resolvedDependencies, (r) => r.directory === resolvedDependency.directory)) {
                _.each(resolvedDependency.dependencies, (d) => {
                    const dependency = {
                        parent: currentModule,
                        name: d,
                        parentDir: resolvedDependency.directory,
                        depth: resolvedDependency.depth + 1,
                    };
                    const shouldAdd = !_.some(queue, (element) => element.parent === dependency.parent &&
                        element.name === dependency.name &&
                        element.parentDir === dependency.parentDir &&
                        element.depth === dependency.depth);
                    if (shouldAdd) {
                        queue.push(dependency);
                    }
                });
                resolvedDependencies.push(resolvedDependency);
            }
        }
        if (ignore && ignore.length > 0) {
            return resolvedDependencies.filter((d) => ignore.indexOf(d.name) === -1);
        }
        return resolvedDependencies;
    }
    findModule(depDescription, resolvedDependencies) {
        var _a, _b;
        try {
            const parentModulesPath = (_a = depDescription === null || depDescription === void 0 ? void 0 : depDescription.parentDir) !== null && _a !== void 0 ? _a : (_b = depDescription === null || depDescription === void 0 ? void 0 : depDescription.parent) === null || _b === void 0 ? void 0 : _b.parentDir;
            const modulePath = require
                .resolve(`${depDescription.name}/package.json`, {
                paths: [parentModulesPath],
            })
                .replace(/[\\/]+package\.json$/, "");
            if (resolvedDependencies.some((r) => {
                return r.name === depDescription.name && r.directory === modulePath;
            })) {
                return null;
            }
            return this.getDependencyData(depDescription.name, modulePath, depDescription.depth);
        }
        catch (err) {
            return null;
        }
    }
    getDependencyData(name, directory, depth) {
        const dependency = {
            name,
            directory,
            depth,
            version: null,
        };
        const packageJsonPath = path.join(directory, constants_1.PACKAGE_JSON_FILE_NAME);
        const packageJsonExists = this.$fs.getLsStats(packageJsonPath).isFile();
        if (packageJsonExists) {
            const packageJsonContents = this.$fs.readJson(packageJsonPath);
            dependency.version = packageJsonContents.version;
            if (!!packageJsonContents.nativescript) {
                dependency.nativescript = packageJsonContents.nativescript;
            }
            dependency.dependencies = _.keys(packageJsonContents.dependencies);
            return dependency;
        }
        return null;
    }
}
exports.NodeModulesDependenciesBuilder = NodeModulesDependenciesBuilder;
yok_1.injector.register("nodeModulesDependenciesBuilder", NodeModulesDependenciesBuilder);
