"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    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) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TypingsCommand = void 0;
const glob_1 = require("glob");
const os_1 = require("os");
const path = require("path");
const color_1 = require("../color");
const yok_1 = require("../common/yok");
class TypingsCommand {
    constructor($logger, $options, $fs, $projectData, $mobileHelper, $childProcess, $hostInfo, $staticConfig, $prompter) {
        this.$logger = $logger;
        this.$options = $options;
        this.$fs = $fs;
        this.$projectData = $projectData;
        this.$mobileHelper = $mobileHelper;
        this.$childProcess = $childProcess;
        this.$hostInfo = $hostInfo;
        this.$staticConfig = $staticConfig;
        this.$prompter = $prompter;
        this.allowedParameters = [];
    }
    execute(args) {
        return __awaiter(this, void 0, void 0, function* () {
            const platform = args[0];
            let result;
            if (this.$mobileHelper.isAndroidPlatform(platform)) {
                result = yield this.handleAndroidTypings();
            }
            else if (this.$mobileHelper.isiOSPlatform(platform)) {
                result = yield this.handleiOSTypings();
            }
            let typingsFolder = "./typings";
            if (this.$options.copyTo) {
                this.$fs.copyFile(path.resolve(this.$projectData.projectDir, "typings"), this.$options.copyTo);
                typingsFolder = this.$options.copyTo;
            }
            if (result !== false) {
                this.$logger.info("Typings have been generated in the following directory:", typingsFolder);
            }
        });
    }
    canExecute(args) {
        return __awaiter(this, void 0, void 0, function* () {
            const platform = args[0];
            this.$mobileHelper.validatePlatformName(platform);
            return true;
        });
    }
    resolveGradleDependencies(target) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            const gradleHome = path.resolve((_a = process.env.GRADLE_USER_HOME) !== null && _a !== void 0 ? _a : path.join((0, os_1.homedir)(), `/.gradle`));
            const gradleFiles = path.resolve(gradleHome, "caches/modules-2/files-2.1/");
            if (!this.$fs.exists(gradleFiles)) {
                this.$logger.warn("No gradle files found");
                return;
            }
            const pattern = `${target.replaceAll(":", "/")}/**/*.{jar,aar}`;
            const res = yield (0, glob_1.glob)(pattern, {
                cwd: gradleFiles,
            });
            if (!res || res.length === 0) {
                this.$logger.warn("No files found");
                return [];
            }
            const items = res.map((item) => {
                const [group, artifact, version, sha1, file] = item.split(path.sep);
                return {
                    id: sha1 + version,
                    group,
                    artifact,
                    version,
                    sha1,
                    file,
                    path: path.resolve(gradleFiles, item),
                };
            });
            this.$logger.clearScreen();
            const choices = yield this.$prompter.promptForChoice(`Select dependencies to generate typings for (${color_1.color.greenBright(target)})`, items
                .sort((a, b) => {
                if (a.artifact < b.artifact)
                    return -1;
                if (a.artifact > b.artifact)
                    return 1;
                return a.version.localeCompare(b.version, undefined, {
                    numeric: true,
                    sensitivity: "base",
                });
            })
                .map((item) => {
                return {
                    title: `${color_1.color.white(item.group)}:${color_1.color.greenBright(item.artifact)}:${color_1.color.yellow(item.version)} - ${color_1.color.cyanBright.bold(item.file)}`,
                    value: item.id,
                };
            }), true, {
                optionsPerPage: process.stdout.rows - 6, // 6 lines are taken up by the instructions
            });
            this.$logger.clearScreen();
            return items
                .filter((item) => choices.includes(item.id))
                .map((item) => item.path);
        });
    }
    handleAndroidTypings() {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            const targets = (_a = this.$options.argv._.slice(2)) !== null && _a !== void 0 ? _a : [];
            const paths = [];
            if (targets.length) {
                for (const target of targets) {
                    try {
                        paths.push(...(yield this.resolveGradleDependencies(target)));
                    }
                    catch (err) {
                        this.$logger.trace(`Failed to resolve gradle dependencies for target "${target}"`, err);
                    }
                }
            }
            if (!paths.length && !(this.$options.jar || this.$options.aar)) {
                this.$logger.warn([
                    "No .jar or .aar file specified. Please specify at least one of the following:",
                    "  - path to .jar file with --jar <jar>",
                    "  - path to .aar file with --aar <aar>",
                ].join("\n"));
                return false;
            }
            this.$fs.ensureDirectoryExists(path.resolve(this.$projectData.projectDir, "typings", "android"));
            const dtsGeneratorPath = path.resolve(this.$projectData.projectDir, "platforms", "android", "build-tools", "dts-generator.jar");
            if (!this.$fs.exists(dtsGeneratorPath)) {
                this.$logger.warn("No platforms folder found, preparing project now...");
                yield this.$childProcess.spawnFromEvent(this.$hostInfo.isWindows ? "ns.cmd" : "ns", ["prepare", "android"], "exit", { stdio: "inherit", shell: this.$hostInfo.isWindows });
            }
            const asArray = (input) => {
                if (!input) {
                    return [];
                }
                if (typeof input === "string") {
                    return [input];
                }
                return input;
            };
            const inputs = [
                ...asArray(this.$options.jar),
                ...asArray(this.$options.aar),
                ...paths,
            ];
            yield this.$childProcess.spawnFromEvent("java", [
                "-jar",
                dtsGeneratorPath,
                "-input",
                ...inputs,
                "-output",
                path.resolve(this.$projectData.projectDir, "typings", "android"),
            ], "exit", { stdio: "inherit" });
        });
    }
    handleiOSTypings() {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.$options.filter !== undefined) {
                this.$logger.warn("--filter flag is not supported yet.");
            }
            this.$fs.ensureDirectoryExists(path.resolve(this.$projectData.projectDir, "typings", "ios"));
            yield this.$childProcess.spawnFromEvent("node", [this.$staticConfig.cliBinPath, "build", "ios"], "exit", {
                env: Object.assign(Object.assign({}, process.env), { TNS_TYPESCRIPT_DECLARATIONS_PATH: path.resolve(this.$projectData.projectDir, "typings", "ios") }),
                stdio: "inherit",
            });
        });
    }
}
exports.TypingsCommand = TypingsCommand;
yok_1.injector.registerCommand("typings", TypingsCommand);
//# sourceMappingURL=typings.js.map