"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.PublishIOS = void 0;
const path = require("path");
const command_params_1 = require("../common/command-params");
const build_data_1 = require("../data/build-data");
const yok_1 = require("../common/yok");
class PublishIOS {
    constructor($applePortalSessionService, $injector, $itmsTransporterService, $logger, $projectData, $options, $prompter, $devicePlatformsConstants, $hostInfo, $errors, $buildController, $platformValidationService) {
        this.$applePortalSessionService = $applePortalSessionService;
        this.$injector = $injector;
        this.$itmsTransporterService = $itmsTransporterService;
        this.$logger = $logger;
        this.$projectData = $projectData;
        this.$options = $options;
        this.$prompter = $prompter;
        this.$devicePlatformsConstants = $devicePlatformsConstants;
        this.$hostInfo = $hostInfo;
        this.$errors = $errors;
        this.$buildController = $buildController;
        this.$platformValidationService = $platformValidationService;
        this.allowedParameters = [
            new command_params_1.StringCommandParameter(this.$injector),
            new command_params_1.StringCommandParameter(this.$injector),
            new command_params_1.StringCommandParameter(this.$injector),
            new command_params_1.StringCommandParameter(this.$injector),
        ];
        this.$projectData.initializeProjectData();
    }
    execute(args) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            yield this.$itmsTransporterService.validate(this.$options.appleApplicationSpecificPassword);
            const username = args[0] ||
                (yield this.$prompter.getString("Apple ID", { allowEmpty: false }));
            const password = args[1] || (yield this.$prompter.getPassword("Apple ID password"));
            const user = yield this.$applePortalSessionService.createUserSession({ username, password }, {
                applicationSpecificPassword: this.$options
                    .appleApplicationSpecificPassword,
                sessionBase64: this.$options.appleSessionBase64,
                requireInteractiveConsole: true,
                requireApplicationSpecificPassword: true,
            });
            if (!user.areCredentialsValid) {
                this.$errors.fail(`Invalid username and password combination. Used '${username}' as the username.`);
            }
            const mobileProvisionIdentifier = (_a = this.$options.provision) !== null && _a !== void 0 ? _a : args[2];
            let ipaFilePath = this.$options.ipa
                ? path.resolve(this.$options.ipa)
                : null;
            if (!mobileProvisionIdentifier && !ipaFilePath) {
                this.$logger.warn("No mobile provision identifier set. A default mobile provision will be used. You can set one in app/App_Resources/iOS/build.xcconfig");
            }
            this.$options.release = true;
            if (!ipaFilePath) {
                const platform = this.$devicePlatformsConstants.iOS.toLowerCase();
                if (mobileProvisionIdentifier) {
                    this.$logger.info("Building .ipa with the selected mobile provision and/or certificate. " +
                        mobileProvisionIdentifier);
                    this.$options.forDevice = true;
                    this.$options.provision = mobileProvisionIdentifier;
                    const buildData = new build_data_1.IOSBuildData(this.$projectData.projectDir, platform, Object.assign(Object.assign({}, this.$options.argv), { watch: false }));
                    ipaFilePath = yield this.$buildController.prepareAndBuild(buildData);
                }
                else {
                    this.$logger.info("No .ipa, mobile provision or certificate set. Perfect! Now we'll build .xcarchive and let Xcode pick the distribution certificate and provisioning profile for you when exporting .ipa for AppStore submission.");
                    const buildData = new build_data_1.IOSBuildData(this.$projectData.projectDir, platform, Object.assign(Object.assign({}, this.$options.argv), { buildForAppStore: true, watch: false }));
                    ipaFilePath = yield this.$buildController.prepareAndBuild(buildData);
                    this.$logger.info(`Export at: ${ipaFilePath}`);
                }
            }
            yield this.$itmsTransporterService.upload({
                credentials: { username, password },
                user,
                applicationSpecificPassword: this.$options
                    .appleApplicationSpecificPassword,
                ipaFilePath,
                shouldExtractIpa: !!this.$options.ipa,
                verboseLogging: this.$logger.getLevel() === "TRACE",
                teamId: this.$options.teamId,
            });
        });
    }
    canExecute(args) {
        return __awaiter(this, void 0, void 0, function* () {
            if (!this.$hostInfo.isDarwin) {
                this.$errors.fail("iOS publishing is only available on macOS.");
            }
            if (!this.$platformValidationService.isPlatformSupportedForOS(this.$devicePlatformsConstants.iOS, this.$projectData)) {
                this.$errors.fail(`Applications for platform ${this.$devicePlatformsConstants.iOS} can not be built on this OS`);
            }
            return true;
        });
    }
}
exports.PublishIOS = PublishIOS;
yok_1.injector.registerCommand(["publish|ios", "appstore|upload"], PublishIOS);
