"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.QuestionMark = exports.N = exports.C = exports.W = exports.CtrlC = exports.ShiftR = exports.R = exports.OpenIOSCommand = exports.ShiftI = exports.I = exports.OpenAndroidCommand = exports.ShiftA = exports.A = void 0;
const fs = require("fs");
const os_1 = require("os");
const path = require("path");
const color_1 = require("../color");
const yok_1 = require("../common/yok");
class A {
    constructor($startService) {
        this.$startService = $startService;
        this.key = "a";
        this.platform = "Android";
        this.description = "Run android app";
    }
    execute() {
        return __awaiter(this, void 0, void 0, function* () {
            this.$startService.runAndroid();
        });
    }
    canExecute(processType) {
        return processType === "start";
    }
}
exports.A = A;
class ShiftA {
    constructor($logger, $liveSyncCommandHelper, $childProcess, $projectData) {
        this.$logger = $logger;
        this.$liveSyncCommandHelper = $liveSyncCommandHelper;
        this.$childProcess = $childProcess;
        this.$projectData = $projectData;
        this.key = "A";
        this.platform = "Android";
        this.description = "Open android project in Android Studio";
        this.willBlockKeyCommandExecution = true;
        this.isInteractive = true;
    }
    execute() {
        return __awaiter(this, void 0, void 0, function* () {
            this.$liveSyncCommandHelper.validatePlatform(this.platform);
            this.$projectData.initializeProjectData();
            const androidDir = `${this.$projectData.platformsDir}/android`;
            if (!fs.existsSync(androidDir)) {
                const prepareCommand = yok_1.injector.resolveCommand("prepare");
                yield prepareCommand.execute([this.platform]);
                if (this.isInteractive) {
                    process.stdin.resume();
                }
            }
            const os = (0, os_1.platform)();
            if (os === "darwin") {
                const possibleStudioPaths = [
                    "/Applications/Android Studio.app",
                    `${process.env.HOME}/Applications/Android Studio.app`,
                ];
                const studioPath = possibleStudioPaths.find((p) => {
                    this.$logger.trace(`Checking for Android Studio at ${p}`);
                    return fs.existsSync(p);
                });
                if (!studioPath) {
                    this.$logger.error("Android Studio is not installed, or not in a standard location.");
                    return;
                }
                this.$childProcess.exec(`open -a "${studioPath}" ${androidDir}`);
            }
            else if (os === "win32") {
                const studioPath = path.join("C:", "Program Files", "Android", "Android Studio", "bin", "studio64.exe");
                if (!fs.existsSync(studioPath)) {
                    this.$logger.error("Android Studio is not installed");
                    return;
                }
                const child = this.$childProcess.spawn(studioPath, [androidDir], {
                    detached: true,
                    stdio: "ignore",
                });
                child.unref();
            }
            else if (os === "linux") {
                if (!fs.existsSync(`/usr/local/android-studio/bin/studio.sh`)) {
                    this.$logger.error("Android Studio is not installed");
                    return;
                }
                this.$childProcess.exec(`/usr/local/android-studio/bin/studio.sh ${androidDir}`);
            }
        });
    }
}
exports.ShiftA = ShiftA;
class OpenAndroidCommand extends ShiftA {
    constructor($logger, $liveSyncCommandHelper, $childProcess, $projectData, $options) {
        super($logger, $liveSyncCommandHelper, $childProcess, $projectData);
        this.$options = $options;
        this.isInteractive = false;
    }
    execute() {
        const _super = Object.create(null, {
            execute: { get: () => super.execute }
        });
        return __awaiter(this, void 0, void 0, function* () {
            this.$options.watch = false;
            _super.execute.call(this);
        });
    }
}
exports.OpenAndroidCommand = OpenAndroidCommand;
class I {
    constructor($startService) {
        this.$startService = $startService;
        this.key = "i";
        this.platform = "iOS";
        this.description = "Run iOS app";
    }
    execute() {
        return __awaiter(this, void 0, void 0, function* () {
            this.$startService.runIOS();
        });
    }
    canExecute(processType) {
        return processType === "start";
    }
}
exports.I = I;
class ShiftI {
    constructor($iOSProjectService, $logger, $childProcess, $projectData, $xcodeSelectService, $xcodebuildArgsService) {
        this.$iOSProjectService = $iOSProjectService;
        this.$logger = $logger;
        this.$childProcess = $childProcess;
        this.$projectData = $projectData;
        this.$xcodeSelectService = $xcodeSelectService;
        this.$xcodebuildArgsService = $xcodebuildArgsService;
        this.key = "I";
        this.platform = "iOS";
        this.description = "Open iOS project in Xcode";
        this.willBlockKeyCommandExecution = true;
        this.isInteractive = true;
    }
    execute() {
        return __awaiter(this, void 0, void 0, function* () {
            const os = (0, os_1.platform)();
            if (os === "darwin") {
                this.$projectData.initializeProjectData();
                const iosDir = path.resolve(this.$projectData.platformsDir, "ios");
                if (!fs.existsSync(iosDir)) {
                    const prepareCommand = yok_1.injector.resolveCommand("prepare");
                    yield prepareCommand.execute(["ios"]);
                    if (this.isInteractive) {
                        process.stdin.resume();
                    }
                }
                const platformData = this.$iOSProjectService.getPlatformData(this.$projectData);
                const xcprojectFile = this.$xcodebuildArgsService.getXcodeProjectArgs(platformData, this.$projectData)[1];
                if (fs.existsSync(xcprojectFile)) {
                    this.$xcodeSelectService
                        .getDeveloperDirectoryPath()
                        .then(() => this.$childProcess.exec(`open ${xcprojectFile}`, {}))
                        .catch((e) => {
                        this.$logger.error(e.message);
                    });
                }
                else {
                    this.$logger.error(`Unable to open project file: ${xcprojectFile}`);
                }
            }
            else {
                this.$logger.error("Opening a project in XCode requires macOS.");
            }
        });
    }
}
exports.ShiftI = ShiftI;
class OpenIOSCommand extends ShiftI {
    constructor($iOSProjectService, $logger, $childProcess, $projectData, $xcodeSelectService, $xcodebuildArgsService, $options) {
        super($iOSProjectService, $logger, $childProcess, $projectData, $xcodeSelectService, $xcodebuildArgsService);
        this.$options = $options;
        this.isInteractive = false;
    }
    execute() {
        const _super = Object.create(null, {
            execute: { get: () => super.execute }
        });
        return __awaiter(this, void 0, void 0, function* () {
            this.$options.watch = false;
            _super.execute.call(this);
        });
    }
}
exports.OpenIOSCommand = OpenIOSCommand;
class R {
    constructor($liveSyncCommandHelper) {
        this.$liveSyncCommandHelper = $liveSyncCommandHelper;
        this.key = "r";
        this.platform = "all";
        this.description = "Rebuild native app if needed and restart";
        this.willBlockKeyCommandExecution = true;
    }
    execute(platform) {
        return __awaiter(this, void 0, void 0, function* () {
            const devices = yield this.$liveSyncCommandHelper.getDeviceInstances(platform);
            yield this.$liveSyncCommandHelper.executeLiveSyncOperation(devices, platform, {
                restartLiveSync: true,
            });
        });
    }
}
exports.R = R;
class ShiftR {
    constructor($liveSyncCommandHelper) {
        this.$liveSyncCommandHelper = $liveSyncCommandHelper;
        this.key = "R";
        this.platform = "all";
        this.description = "Force rebuild native app and restart";
        this.willBlockKeyCommandExecution = true;
    }
    execute(platform) {
        return __awaiter(this, void 0, void 0, function* () {
            const devices = yield this.$liveSyncCommandHelper.getDeviceInstances(platform);
            yield this.$liveSyncCommandHelper.executeLiveSyncOperation(devices, platform, {
                skipNativePrepare: false,
                forceRebuildNativeApp: true,
                restartLiveSync: true,
            });
        });
    }
}
exports.ShiftR = ShiftR;
class CtrlC {
    constructor() {
        this.key = "\u0003" /* SpecialKeys.CtrlC */;
        this.platform = "all";
        this.willBlockKeyCommandExecution = false;
    }
    execute() {
        return __awaiter(this, void 0, void 0, function* () {
            process.exit();
        });
    }
}
exports.CtrlC = CtrlC;
class W {
    constructor($prepareController) {
        this.$prepareController = $prepareController;
        this.key = "w";
        this.platform = "all";
        this.description = "Toggle file watcher";
        this.willBlockKeyCommandExecution = true;
    }
    execute() {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const paused = yield this.$prepareController.toggleFileWatcher();
                process.stdout.write(paused
                    ? color_1.color.gray("Paused watching file changes... Press 'w' to resume.")
                    : color_1.color.bgGreen("Resumed watching file changes"));
            }
            catch (e) { }
        });
    }
}
exports.W = W;
class C {
    constructor($childProcess, $liveSyncCommandHelper) {
        this.$childProcess = $childProcess;
        this.$liveSyncCommandHelper = $liveSyncCommandHelper;
        this.key = "c";
        this.platform = "all";
        this.description = "Clean project";
        this.willBlockKeyCommandExecution = true;
    }
    execute() {
        return __awaiter(this, void 0, void 0, function* () {
            yield this.$liveSyncCommandHelper.stop();
            const clean = this.$childProcess.spawn("ns", ["clean"]);
            clean.stdout.on("data", (data) => {
                process.stdout.write(data);
                if (data.toString().includes("Project successfully cleaned.") ||
                    data.toString().includes("Project unsuccessfully cleaned.")) {
                    clean.kill("SIGINT");
                }
            });
        });
    }
}
exports.C = C;
class N {
    constructor() {
        this.key = "n";
        this.platform = "all";
        this.description = "Install dependencies";
        this.willBlockKeyCommandExecution = true;
    }
    execute(platform) {
        return __awaiter(this, void 0, void 0, function* () {
            const install = yok_1.injector.resolveCommand("install");
            yield install.execute([]);
            process.stdin.resume();
        });
    }
}
exports.N = N;
class QuestionMark {
    constructor($keyCommandHelper) {
        this.$keyCommandHelper = $keyCommandHelper;
        this.key = "?" /* SpecialKeys.QuestionMark */;
        this.platform = "all";
        this.description = "Show this help";
        this.willBlockKeyCommandExecution = true;
    }
    execute(platform_) {
        return __awaiter(this, void 0, void 0, function* () {
            let platform;
            switch (platform_.toLowerCase()) {
                case "android":
                    platform = "Android";
                    break;
                case "ios":
                    platform = "iOS";
                    break;
                default:
                    platform = "all";
                    break;
            }
            this.$keyCommandHelper.printCommands(platform);
            process.stdin.resume();
        });
    }
}
exports.QuestionMark = QuestionMark;
yok_1.injector.registerKeyCommand("a", A);
yok_1.injector.registerKeyCommand("i", I);
yok_1.injector.registerKeyCommand("A", ShiftA);
yok_1.injector.registerKeyCommand("I", ShiftI);
yok_1.injector.registerKeyCommand("r", R);
yok_1.injector.registerKeyCommand("R", ShiftR);
yok_1.injector.registerKeyCommand("w", W);
yok_1.injector.registerKeyCommand("c", C);
yok_1.injector.registerKeyCommand("A", ShiftA);
yok_1.injector.registerKeyCommand("n", N);
yok_1.injector.registerKeyCommand("?" /* SpecialKeys.QuestionMark */, QuestionMark);
yok_1.injector.registerKeyCommand("\u0003" /* SpecialKeys.CtrlC */, CtrlC);
yok_1.injector.registerCommand("open|ios", OpenIOSCommand);
yok_1.injector.registerCommand("open|android", OpenAndroidCommand);
//# sourceMappingURL=index.js.map