"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());
    });
};
const install_1 = require('./install');
/**
 * Install multiple modules into `modules`.
 *
 * @example
 *     ctx = { }
 *     installMultiple(ctx, { minimatch: '^2.0.0' }, {chokidar: '^1.6.0'}, './node_modules')
 */
function installMultiple(ctx, requiredPkgsMap, optionalPkgsMap, modules, options) {
    requiredPkgsMap = requiredPkgsMap || {};
    optionalPkgsMap = optionalPkgsMap || {};
    const optionalPkgs = Object.keys(optionalPkgsMap)
        .map(pkgName => pkgMeta(pkgName, optionalPkgsMap[pkgName], true));
    const requiredPkgs = Object.keys(requiredPkgsMap)
        .filter(pkgName => !optionalPkgsMap[pkgName])
        .map(pkgName => pkgMeta(pkgName, requiredPkgsMap[pkgName], false));
    ctx.storeJson.packages = ctx.storeJson.packages || {};
    return Promise.all(optionalPkgs.concat(requiredPkgs).map(function (pkg) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const dependency = yield install_1.default(ctx, pkg, modules, options);
                ctx.storeJson.packages[options.dependent] = ctx.storeJson.packages[options.dependent] || {};
                ctx.storeJson.packages[options.dependent].dependencies = ctx.storeJson.packages[options.dependent].dependencies || {};
                // NOTE: the current install implementation
                // does not return enough info for packages that were already installed
                if (!dependency.fromCache) {
                    ctx.storeJson.packages[options.dependent].dependencies[dependency.pkg.name] = dependency.id;
                    ctx.storeJson.packages[dependency.id] = ctx.storeJson.packages[dependency.id] || {};
                    ctx.storeJson.packages[dependency.id].dependents = ctx.storeJson.packages[dependency.id].dependents || [];
                    if (ctx.storeJson.packages[dependency.id].dependents.indexOf(options.dependent) === -1) {
                        ctx.storeJson.packages[dependency.id].dependents.push(options.dependent);
                    }
                }
                return dependency;
            }
            catch (err) {
                if (pkg.optional) {
                    console.log('Skipping failed optional dependency ' + pkg.rawSpec + ':');
                    console.log(err.message || err);
                    return null; // is it OK to return null?
                }
                throw err;
            }
        });
    }));
}
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = installMultiple;
function pkgMeta(name, version, optional) {
    return {
        rawSpec: version === '*' ? name : `${name}@${version}`,
        optional
    };
}
//# sourceMappingURL=installMultiple.js.map