"use strict";
const path = require("path");
const shelljs = require("shelljs");
const constants = require("../../constants");
const minimatch = require("minimatch");
const Future = require("fibers/future");
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";
                let deleteFilesFutures = allFiles.filter(file => minimatch(file, matchPattern, { nocase: true })).map(file => this.$fs.deleteFile(file));
                Future.wait(deleteFilesFutures);
                shelljs.rm("-rf", path.join(tnsCoreModulesResourcePath, "node_modules"));
                shelljs.cp("-Rf", path.join(tnsCoreModulesResourcePath, "*"), this.outputRoot);
                shelljs.rm("-rf", tnsCoreModulesResourcePath);
            }
        }
    }
    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) {
        this.$platformsData.getPlatformData(platform).platformProjectService.beforePrepareAllPlugins(dependencies).wait();
    }
    afterPrepare(dependencies, platform) {
        this.$platformsData.getPlatformData(platform).platformProjectService.afterPrepareAllPlugins().wait();
        this.writePreparedDependencyInfo(dependencies, platform);
    }
    writePreparedDependencyInfo(dependencies, platform) {
        let prepareData = {};
        _.values(dependencies).forEach(d => {
            prepareData[d.name] = true;
        });
        this.$fs.createDirectory(this.preparedPlatformsDir(platform)).wait();
        this.$fs.writeJson(this.preparedPlatformsFile(platform), prepareData, "    ", "utf8").wait();
    }
    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)).wait()) {
            return {};
        }
        return this.$fs.readJson(this.preparedPlatformsFile(platform), "utf8").wait();
    }
    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) {
        if (_.isEmpty(dependencies) || this.allPrepared(dependencies, platform)) {
            return;
        }
        this.beforePrepare(dependencies, platform);
        _.each(dependencies, dependency => {
            let isPlugin = !!dependency.nativescript;
            if (isPlugin) {
                this.$pluginsService.prepare(dependency, platform).wait();
            }
        });
        this.afterPrepare(dependencies, platform);
    }
}
exports.NpmPluginPrepare = NpmPluginPrepare;
