"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 os_1 = require("os");
class DebugPlatformCommand {
    constructor(debugService, $devicesService, $injector, $config, $usbLiveSyncService, $debugDataService, $platformService, $projectData, $options, $platformsData, $logger) {
        this.debugService = debugService;
        this.$devicesService = $devicesService;
        this.$injector = $injector;
        this.$config = $config;
        this.$usbLiveSyncService = $usbLiveSyncService;
        this.$debugDataService = $debugDataService;
        this.$platformService = $platformService;
        this.$projectData = $projectData;
        this.$options = $options;
        this.$platformsData = $platformsData;
        this.$logger = $logger;
        this.allowedParameters = [];
        this.$projectData.initializeProjectData();
    }
    execute(args) {
        return __awaiter(this, void 0, void 0, function* () {
            const debugOptions = this.$options;
            const deployOptions = {
                clean: this.$options.clean,
                device: this.$options.device,
                emulator: this.$options.emulator,
                platformTemplate: this.$options.platformTemplate,
                projectDir: this.$options.path,
                release: this.$options.release,
                provision: this.$options.provision,
                teamId: this.$options.teamId
            };
            let debugData = this.$debugDataService.createDebugData(this.$projectData, this.$options);
            yield this.$platformService.trackProjectType(this.$projectData);
            if (this.$options.start) {
                return this.printDebugInformation(yield this.debugService.debug(debugData, debugOptions));
            }
            const appFilesUpdaterOptions = { bundle: this.$options.bundle, release: this.$options.release };
            yield this.$platformService.deployPlatform(this.$devicesService.platform, appFilesUpdaterOptions, deployOptions, this.$projectData, this.$options);
            this.$config.debugLivesync = true;
            let applicationReloadAction = (deviceAppData) => __awaiter(this, void 0, void 0, function* () {
                let projectData = this.$injector.resolve("projectData");
                yield this.debugService.debugStop();
                let applicationId = deviceAppData.appIdentifier;
                yield deviceAppData.device.applicationManager.stopApplication(applicationId, projectData.projectName);
                const buildConfig = _.merge({ buildForDevice: !deviceAppData.device.isEmulator }, deployOptions);
                debugData.pathToAppPackage = this.$platformService.lastOutputPath(this.debugService.platform, buildConfig, projectData);
                this.printDebugInformation(yield this.debugService.debug(debugData, debugOptions));
            });
            return this.$usbLiveSyncService.liveSync(this.$devicesService.platform, this.$projectData, applicationReloadAction);
        });
    }
    canExecute(args) {
        return __awaiter(this, void 0, void 0, function* () {
            yield this.$devicesService.initialize({ platform: this.debugService.platform, deviceId: this.$options.device });
            if (this.$options.emulator || this.$devicesService.deviceCount === 0) {
                return true;
            }
            if (this.$devicesService.deviceCount > 1) {
                this.$options.emulator = true;
                this.$logger.warn("Multiple devices found! Starting debugger on emulator. If you want to debug on specific device please select device with --device option.".yellow.bold);
            }
            return true;
        });
    }
    printDebugInformation(information) {
        _.each(information, i => {
            this.$logger.info(`To start debugging, open the following URL in Chrome:${os_1.EOL}${i}${os_1.EOL}`.cyan);
        });
    }
}
exports.DebugPlatformCommand = DebugPlatformCommand;
class DebugIOSCommand extends DebugPlatformCommand {
    constructor($logger, $iOSDebugService, $devicesService, $injector, $devicePlatformsConstants, $config, $usbLiveSyncService, $debugDataService, $platformService, $options, $projectData, $platformsData, $iosDeviceOperations) {
        super($iOSDebugService, $devicesService, $injector, $config, $usbLiveSyncService, $debugDataService, $platformService, $projectData, $options, $platformsData, $logger);
        this.$logger = $logger;
        $iosDeviceOperations.setShouldDispose(false);
    }
    canExecute(args) {
        const _super = name => super[name];
        return __awaiter(this, void 0, void 0, function* () {
            return (yield _super("canExecute").call(this, args)) && (yield this.$platformService.validateOptions(this.$options.provision, this.$projectData, this.$platformsData.availablePlatforms.iOS));
        });
    }
    printDebugInformation(information) {
        if (this.$options.chrome) {
            super.printDebugInformation(information);
        }
    }
}
exports.DebugIOSCommand = DebugIOSCommand;
$injector.registerCommand("debug|ios", DebugIOSCommand);
class DebugAndroidCommand extends DebugPlatformCommand {
    constructor($logger, $androidDebugService, $devicesService, $injector, $devicePlatformsConstants, $config, $usbLiveSyncService, $debugDataService, $platformService, $options, $projectData, $platformsData) {
        super($androidDebugService, $devicesService, $injector, $config, $usbLiveSyncService, $debugDataService, $platformService, $projectData, $options, $platformsData, $logger);
    }
    canExecute(args) {
        const _super = name => super[name];
        return __awaiter(this, void 0, void 0, function* () {
            return (yield _super("canExecute").call(this, args)) && (yield this.$platformService.validateOptions(this.$options.provision, this.$projectData, this.$platformsData.availablePlatforms.Android));
        });
    }
}
exports.DebugAndroidCommand = DebugAndroidCommand;
$injector.registerCommand("debug|android", DebugAndroidCommand);
