"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());
    });
};
class TestCommandBase {
    constructor() {
        this.allowedParameters = [];
    }
    execute(args) {
        return __awaiter(this, void 0, void 0, function* () {
            let devices = [];
            if (this.$options.debugBrk) {
                yield this.$devicesService.initialize({
                    platform: this.platform,
                    deviceId: this.$options.device,
                    emulator: this.$options.emulator,
                    skipInferPlatform: !this.platform,
                    sdk: this.$options.sdk
                });
                const selectedDeviceForDebug = yield this.$devicesService.pickSingleDevice({
                    onlyEmulators: this.$options.emulator,
                    onlyDevices: this.$options.forDevice,
                    deviceId: this.$options.device
                });
                devices = [selectedDeviceForDebug];
            }
            else {
                devices = yield this.$liveSyncCommandHelper.getDeviceInstances(this.platform);
            }
            if (!this.$options.env) {
                this.$options.env = {};
            }
            this.$options.env.unitTesting = true;
            const liveSyncInfo = this.$liveSyncCommandHelper.getLiveSyncData(this.$projectData.projectDir);
            const deviceDebugMap = {};
            devices.forEach(device => deviceDebugMap[device.deviceInfo.identifier] = this.$options.debugBrk);
            const deviceDescriptors = yield this.$liveSyncCommandHelper.createDeviceDescriptors(devices, this.platform, { deviceDebugMap });
            yield this.$testExecutionService.startKarmaServer(this.platform, liveSyncInfo, deviceDescriptors);
        });
    }
    canExecute(args) {
        return __awaiter(this, void 0, void 0, function* () {
            this.$projectData.initializeProjectData();
            this.$analyticsService.setShouldDispose(this.$options.justlaunch || !this.$options.watch);
            this.$cleanupService.setShouldDispose(this.$options.justlaunch || !this.$options.watch);
            const output = yield this.$platformEnvironmentRequirements.checkEnvironmentRequirements({
                platform: this.platform,
                projectDir: this.$projectData.projectDir,
                options: this.$options,
                notConfiguredEnvOptions: {
                    hideSyncToPreviewAppOption: true,
                    hideCloudBuildOption: true
                }
            });
            const canStartKarmaServer = yield this.$testExecutionService.canStartKarmaServer(this.$projectData);
            if (!canStartKarmaServer) {
                this.$errors.fail({
                    formatStr: "Error: In order to run unit tests, your project must already be configured by running $ tns test init.",
                    suppressCommandHelp: true,
                    errorCode: 133
                });
            }
            return output.canExecute && canStartKarmaServer;
        });
    }
}
class TestAndroidCommand extends TestCommandBase {
    constructor($projectData, $testExecutionService, $analyticsService, $options, $platformEnvironmentRequirements, $errors, $cleanupService, $liveSyncCommandHelper, $devicesService) {
        super();
        this.$projectData = $projectData;
        this.$testExecutionService = $testExecutionService;
        this.$analyticsService = $analyticsService;
        this.$options = $options;
        this.$platformEnvironmentRequirements = $platformEnvironmentRequirements;
        this.$errors = $errors;
        this.$cleanupService = $cleanupService;
        this.$liveSyncCommandHelper = $liveSyncCommandHelper;
        this.$devicesService = $devicesService;
        this.platform = "android";
    }
}
class TestIosCommand extends TestCommandBase {
    constructor($projectData, $testExecutionService, $analyticsService, $options, $platformEnvironmentRequirements, $errors, $cleanupService, $liveSyncCommandHelper, $devicesService) {
        super();
        this.$projectData = $projectData;
        this.$testExecutionService = $testExecutionService;
        this.$analyticsService = $analyticsService;
        this.$options = $options;
        this.$platformEnvironmentRequirements = $platformEnvironmentRequirements;
        this.$errors = $errors;
        this.$cleanupService = $cleanupService;
        this.$liveSyncCommandHelper = $liveSyncCommandHelper;
        this.$devicesService = $devicesService;
        this.platform = "iOS";
    }
}
$injector.registerCommand("test|android", TestAndroidCommand);
$injector.registerCommand("test|ios", TestIosCommand);
