"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 path = require("path");
const shelljs = require("shelljs");
const constants = require("../../constants");
const minimatch = require("minimatch");
class TnsModulesCopy {
    constructor(outputRoot, $options, $fs) {
        this.outputRoot = outputRoot;
        this.$options = $options;
        this.$fs = $fs;
    }
    copyModules(dependencies, platform) {
        for (let entry in dependencies) {
            let dependency = dependencies[entry];
            this.copyDependencyDir(dependency);
            if (dependency.name === constants.TNS_CORE_MODULES_NAME) {
                let tnsCoreModulesResourcePath = path.join(this.outputRoot, constants.TNS_CORE_MODULES_NAME);
                let allFiles = this.$fs.enumerateFilesInDirectorySync(tnsCoreModulesResourcePath);
                let matchPattern = this.$options.release ? "**/*.ts" : "**/*.d.ts";
                allFiles.filter(file => minimatch(file, matchPattern, { nocase: true })).map(file => this.$fs.deleteFile(file));
                shelljs.rm("-rf", path.join(tnsCoreModulesResourcePath, "node_modules"));
            }
        }
    }
    copyDependencyDir(dependency) {
        if (dependency.depth === 0) {
            let isScoped = dependency.name.indexOf("@") === 0;
            let targetDir = this.outputRoot;
            if (isScoped) {
                targetDir = path.join(this.outputRoot, dependency.name.substring(0, dependency.name.indexOf("/")));
            }
            shelljs.mkdir("-p", targetDir);
            shelljs.cp("-Rf", dependency.directory, targetDir);
            const targetPackageDir = path.join(targetDir, dependency.name);
            shelljs.rm("-rf", path.join(targetPackageDir, "platforms"));
        }
    }
}
exports.TnsModulesCopy = TnsModulesCopy;
class NpmPluginPrepare {
    constructor($fs, $pluginsService, $platformsData) {
        this.$fs = $fs;
        this.$pluginsService = $pluginsService;
        this.$platformsData = $platformsData;
    }
    beforePrepare(dependencies, platform) {
        return __awaiter(this, void 0, void 0, function* () {
            yield this.$platformsData.getPlatformData(platform).platformProjectService.beforePrepareAllPlugins(dependencies);
        });
    }
    afterPrepare(dependencies, platform) {
        return __awaiter(this, void 0, void 0, function* () {
            yield this.$platformsData.getPlatformData(platform).platformProjectService.afterPrepareAllPlugins();
            this.writePreparedDependencyInfo(dependencies, platform);
        });
    }
    writePreparedDependencyInfo(dependencies, platform) {
        let prepareData = {};
        _.values(dependencies).forEach(d => {
            prepareData[d.name] = true;
        });
        this.$fs.createDirectory(this.preparedPlatformsDir(platform));
        this.$fs.writeJson(this.preparedPlatformsFile(platform), prepareData, "    ", "utf8");
    }
    preparedPlatformsDir(platform) {
        const platformRoot = this.$platformsData.getPlatformData(platform).projectRoot;
        if (/android/i.test(platform)) {
            return path.join(platformRoot, "build", "intermediates");
        }
        else if (/ios/i.test(platform)) {
            return path.join(platformRoot, "build");
        }
        else {
            throw new Error("Invalid platform: " + platform);
        }
    }
    preparedPlatformsFile(platform) {
        return path.join(this.preparedPlatformsDir(platform), "prepared-platforms.json");
    }
    getPreviouslyPreparedDependencies(platform) {
        if (!this.$fs.exists(this.preparedPlatformsFile(platform))) {
            return {};
        }
        return this.$fs.readJson(this.preparedPlatformsFile(platform), "utf8");
    }
    allPrepared(dependencies, platform) {
        let result = true;
        const previouslyPrepared = this.getPreviouslyPreparedDependencies(platform);
        _.values(dependencies).forEach(d => {
            if (!previouslyPrepared[d.name]) {
                result = false;
            }
        });
        return result;
    }
    preparePlugins(dependencies, platform) {
        return __awaiter(this, void 0, void 0, function* () {
            if (_.isEmpty(dependencies) || this.allPrepared(dependencies, platform)) {
                return;
            }
            yield this.beforePrepare(dependencies, platform);
            for (let dependencyKey in dependencies) {
                const dependency = dependencies[dependencyKey];
                let isPlugin = !!dependency.nativescript;
                if (isPlugin) {
                    yield this.$pluginsService.prepare(dependency, platform);
                }
            }
            yield this.afterPrepare(dependencies, platform);
        });
    }
}
exports.NpmPluginPrepare = NpmPluginPrepare;
