"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());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const path = require("path");
const constants_1 = require("../../constants");
const helpers = require("../../common/helpers");
class IOSSigningService {
    constructor($errors, $fs, $iOSProvisionService, $logger, $pbxprojDomXcode, $prompter, $xcconfigService, $xcprojService) {
        this.$errors = $errors;
        this.$fs = $fs;
        this.$iOSProvisionService = $iOSProvisionService;
        this.$logger = $logger;
        this.$pbxprojDomXcode = $pbxprojDomXcode;
        this.$prompter = $prompter;
        this.$xcconfigService = $xcconfigService;
        this.$xcprojService = $xcprojService;
    }
    setupSigningForDevice(projectRoot, projectData, iOSBuildData) {
        return __awaiter(this, void 0, void 0, function* () {
            const xcode = this.$pbxprojDomXcode.Xcode.open(this.getPbxProjPath(projectData, projectRoot));
            const signing = xcode.getSigning(projectData.projectName);
            const hasProvisioningProfileInXCConfig = this.readXCConfigProvisioningProfileSpecifierForIPhoneOs(projectData) ||
                this.readXCConfigProvisioningProfileSpecifier(projectData) ||
                this.readXCConfigProvisioningProfileForIPhoneOs(projectData) ||
                this.readXCConfigProvisioningProfile(projectData);
            if (hasProvisioningProfileInXCConfig && (!signing || signing.style !== "Manual")) {
                xcode.setManualSigningStyle(projectData.projectName);
                xcode.save();
            }
            else if (!iOSBuildData.provision && !(signing && signing.style === "Manual" && !iOSBuildData.teamId)) {
                const teamId = yield this.getDevelopmentTeam(projectData, projectRoot, iOSBuildData.teamId);
                yield this.setupSigningFromTeam(projectRoot, projectData, teamId);
            }
        });
    }
    setupSigningFromTeam(projectRoot, projectData, teamId) {
        return __awaiter(this, void 0, void 0, function* () {
            const xcode = this.$pbxprojDomXcode.Xcode.open(this.getPbxProjPath(projectData, projectRoot));
            const signing = xcode.getSigning(projectData.projectName);
            let shouldUpdateXcode = false;
            if (signing && signing.style === "Automatic") {
                if (signing.team !== teamId) {
                    const teamIdsForName = yield this.$iOSProvisionService.getTeamIdsWithName(teamId);
                    if (!teamIdsForName.some(id => id === signing.team)) {
                        shouldUpdateXcode = true;
                    }
                }
            }
            else {
                shouldUpdateXcode = true;
            }
            if (shouldUpdateXcode) {
                const teamIdsForName = yield this.$iOSProvisionService.getTeamIdsWithName(teamId);
                if (teamIdsForName.length > 0) {
                    this.$logger.trace(`Team id ${teamIdsForName[0]} will be used for team name "${teamId}".`);
                    teamId = teamIdsForName[0];
                }
                xcode.setAutomaticSigningStyle(projectData.projectName, teamId);
                xcode.setAutomaticSigningStyleByTargetProductTypesList([
                    constants_1.IOSNativeTargetProductTypes.appExtension,
                    constants_1.IOSNativeTargetProductTypes.watchApp,
                    constants_1.IOSNativeTargetProductTypes.watchExtension
                ], teamId);
                xcode.save();
                this.$logger.trace(`Set Automatic signing style and team id ${teamId}.`);
            }
            else {
                this.$logger.trace(`The specified ${teamId} is already set in the Xcode.`);
            }
        });
    }
    setupSigningFromProvision(projectRoot, projectData, provision, mobileProvisionData) {
        return __awaiter(this, void 0, void 0, function* () {
            if (!provision) {
                return;
            }
            const xcode = this.$pbxprojDomXcode.Xcode.open(this.getPbxProjPath(projectData, projectRoot));
            const signing = xcode.getSigning(projectData.projectName);
            let shouldUpdateXcode = false;
            if (signing && signing.style === "Manual") {
                for (const config in signing.configurations) {
                    const options = signing.configurations[config];
                    if (options.name !== provision && options.uuid !== provision) {
                        shouldUpdateXcode = true;
                        break;
                    }
                }
            }
            else {
                shouldUpdateXcode = true;
            }
            if (shouldUpdateXcode) {
                const pickStart = Date.now();
                const mobileprovision = mobileProvisionData || (yield this.$iOSProvisionService.pick(provision, projectData.projectIdentifiers.ios));
                const pickEnd = Date.now();
                this.$logger.trace("Searched and " + (mobileprovision ? "found" : "failed to find ") + " matching provisioning profile. (" + (pickEnd - pickStart) + "ms.)");
                if (!mobileprovision) {
                    this.$errors.failWithoutHelp("Failed to find mobile provision with UUID or Name: " + provision);
                }
                const configuration = {
                    team: mobileprovision.TeamIdentifier && mobileprovision.TeamIdentifier.length > 0 ? mobileprovision.TeamIdentifier[0] : undefined,
                    uuid: mobileprovision.UUID,
                    name: mobileprovision.Name,
                    identity: mobileprovision.Type === "Development" ? "iPhone Developer" : "iPhone Distribution"
                };
                xcode.setManualSigningStyle(projectData.projectName, configuration);
                xcode.setManualSigningStyleByTargetProductTypesList([
                    constants_1.IOSNativeTargetProductTypes.appExtension,
                    constants_1.IOSNativeTargetProductTypes.watchApp,
                    constants_1.IOSNativeTargetProductTypes.watchExtension
                ], configuration);
                xcode.save();
                this.$logger.trace(`Set Manual signing style and provisioning profile: ${mobileprovision.Name} (${mobileprovision.UUID})`);
            }
            else {
                this.$logger.trace(`The specified provisioning profile is already set in the Xcode: ${provision}`);
            }
        });
    }
    getBuildXCConfigFilePath(projectData) {
        return path.join(projectData.appResourcesDirectoryPath, constants_1.iOSAppResourcesFolderName, constants_1.BUILD_XCCONFIG_FILE_NAME);
    }
    getPbxProjPath(projectData, projectRoot) {
        return path.join(this.$xcprojService.getXcodeprojPath(projectData, projectRoot), "project.pbxproj");
    }
    getDevelopmentTeam(projectData, projectRoot, teamId) {
        return __awaiter(this, void 0, void 0, function* () {
            teamId = teamId || this.readXCConfigDevelopmentTeam(projectData);
            if (!teamId) {
                const teams = yield this.$iOSProvisionService.getDevelopmentTeams();
                this.$logger.warn("Xcode requires a team id to be specified when building for device.");
                this.$logger.warn("You can specify the team id by setting the DEVELOPMENT_TEAM setting in build.xcconfig file located in App_Resources folder of your app, or by using the --teamId option when calling run, debug or livesync commands.");
                if (teams.length === 1) {
                    teamId = teams[0].id;
                    this.$logger.warn("Found and using the following development team installed on your system: " + teams[0].name + " (" + teams[0].id + ")");
                }
                else if (teams.length > 0) {
                    if (!helpers.isInteractive()) {
                        this.$errors.failWithoutHelp(`Unable to determine default development team. Available development teams are: ${_.map(teams, team => team.id)}. Specify team in app/App_Resources/iOS/build.xcconfig file in the following way: DEVELOPMENT_TEAM = <team id>`);
                    }
                    const choices = [];
                    for (const team of teams) {
                        choices.push(team.name + " (" + team.id + ")");
                    }
                    const choice = yield this.$prompter.promptForChoice('Found multiple development teams, select one:', choices);
                    teamId = teams[choices.indexOf(choice)].id;
                    const choicesPersist = [
                        "Yes, set the DEVELOPMENT_TEAM setting in build.xcconfig file.",
                        "Yes, persist the team id in platforms folder.",
                        "No, don't persist this setting."
                    ];
                    const choicePersist = yield this.$prompter.promptForChoice("Do you want to make teamId: " + teamId + " a persistent choice for your app?", choicesPersist);
                    switch (choicesPersist.indexOf(choicePersist)) {
                        case 0:
                            const xcconfigFile = path.join(projectData.appResourcesDirectoryPath, "iOS", constants_1.BUILD_XCCONFIG_FILE_NAME);
                            this.$fs.appendFile(xcconfigFile, "\nDEVELOPMENT_TEAM = " + teamId + "\n");
                            break;
                        case 1:
                            this.$fs.writeFile(path.join(projectRoot, "teamid"), teamId);
                            break;
                        default:
                            break;
                    }
                }
            }
            this.$logger.trace(`Selected teamId is '${teamId}'.`);
            return teamId;
        });
    }
    readXCConfigDevelopmentTeam(projectData) {
        return this.$xcconfigService.readPropertyValue(this.getBuildXCConfigFilePath(projectData), "DEVELOPMENT_TEAM");
    }
    readXCConfigProvisioningProfile(projectData) {
        return this.$xcconfigService.readPropertyValue(this.getBuildXCConfigFilePath(projectData), "PROVISIONING_PROFILE");
    }
    readXCConfigProvisioningProfileForIPhoneOs(projectData) {
        return this.$xcconfigService.readPropertyValue(this.getBuildXCConfigFilePath(projectData), "PROVISIONING_PROFILE[sdk=iphoneos*]");
    }
    readXCConfigProvisioningProfileSpecifier(projectData) {
        return this.$xcconfigService.readPropertyValue(this.getBuildXCConfigFilePath(projectData), "PROVISIONING_PROFILE_SPECIFIER");
    }
    readXCConfigProvisioningProfileSpecifierForIPhoneOs(projectData) {
        return this.$xcconfigService.readPropertyValue(this.getBuildXCConfigFilePath(projectData), "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]");
    }
}
exports.IOSSigningService = IOSSigningService;
$injector.register("iOSSigningService", IOSSigningService);
