"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
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.ITMSTransporterService = void 0;
const path = require("path");
const constants_1 = require("../constants");
const helpers_1 = require("../common/helpers");
const decorators_1 = require("../common/decorators");
const yok_1 = require("../common/yok");
class ITMSTransporterService {
    constructor($applePortalApplicationService, $childProcess, $errors, $fs, $injector, $logger, $plistParser, $xcodeSelectService, $tempService) {
        this.$applePortalApplicationService = $applePortalApplicationService;
        this.$childProcess = $childProcess;
        this.$errors = $errors;
        this.$fs = $fs;
        this.$injector = $injector;
        this.$logger = $logger;
        this.$plistParser = $plistParser;
        this.$xcodeSelectService = $xcodeSelectService;
        this.$tempService = $tempService;
    }
    get $projectData() {
        return this.$injector.resolve("projectData");
    }
    validate(appSpecificPassword) {
        return __awaiter(this, void 0, void 0, function* () {
            const itmsTransporterPath = yield this.getITMSTransporterPath();
            const version = yield this.$xcodeSelectService.getXcodeVersion();
            if (+version.major < 14) {
                if (!this.$fs.exists(itmsTransporterPath)) {
                    this.$errors.fail("iTMS Transporter not found on this machine - make sure your Xcode installation is not damaged.");
                }
            }
            else {
                const altoolPath = yield this.getAltoolPath();
                if (!this.$fs.exists(altoolPath)) {
                    this.$errors.fail("altool not found on this machine - make sure your Xcode installation is not damaged.");
                }
                if (!appSpecificPassword) {
                    this.$errors.fail("An app-specific password is required from xCode versions 14 and above, Use the --appleApplicationSpecificPassword to supply it.");
                }
            }
        });
    }
    upload(data) {
        return __awaiter(this, void 0, void 0, function* () {
            const version = yield this.$xcodeSelectService.getXcodeVersion();
            if (+version.major < 14) {
                yield this.upload_iTMSTransporter(data);
            }
            else {
                yield this.upload_altool(data);
            }
        });
    }
    upload_iTMSTransporter(data) {
        return __awaiter(this, void 0, void 0, function* () {
            const itmsTransporterPath = yield this.getITMSTransporterPath();
            const ipaFileName = "app.ipa";
            const itmsDirectory = yield this.$tempService.mkdirSync("itms-");
            const innerDirectory = path.join(itmsDirectory, "mybundle.itmsp");
            const ipaFileLocation = path.join(innerDirectory, ipaFileName);
            const loggingLevel = data.verboseLogging
                ? constants_1.ITMSConstants.VerboseLoggingLevels.Verbose
                : constants_1.ITMSConstants.VerboseLoggingLevels.Informational;
            const bundleId = yield this.getBundleIdentifier(data);
            const application = yield this.$applePortalApplicationService.getApplicationByBundleId(data.user, bundleId);
            this.$fs.createDirectory(innerDirectory);
            this.$fs.copyFile(data.ipaFilePath, ipaFileLocation);
            const ipaFileHash = yield this.$fs.getFileShasum(ipaFileLocation, {
                algorithm: "md5",
            });
            const ipaFileSize = this.$fs.getFileSize(ipaFileLocation);
            const metadata = this.getITMSMetadataXml(application.adamId, ipaFileName, ipaFileHash, ipaFileSize);
            this.$fs.writeFile(path.join(innerDirectory, constants_1.ITMSConstants.ApplicationMetadataFile), metadata);
            const password = data.user.isTwoFactorAuthenticationEnabled
                ? data.applicationSpecificPassword
                : data.credentials.password;
            yield this.$childProcess.spawnFromEvent(itmsTransporterPath, [
                "-m",
                "upload",
                "-f",
                itmsDirectory,
                "-u",
                (0, helpers_1.quoteString)(data.credentials.username),
                "-p",
                (0, helpers_1.quoteString)(password),
                "-v",
                loggingLevel,
            ], "close", { stdio: "inherit" });
        });
    }
    upload_altool(data) {
        return __awaiter(this, void 0, void 0, function* () {
            const altoolPath = yield this.getAltoolPath();
            const ipaFileName = "app.ipa";
            const itmsDirectory = yield this.$tempService.mkdirSync("itms-");
            const innerDirectory = path.join(itmsDirectory, "mybundle.itmsp");
            const ipaFileLocation = path.join(innerDirectory, ipaFileName);
            this.$fs.createDirectory(innerDirectory);
            this.$fs.copyFile(data.ipaFilePath, ipaFileLocation);
            const password = data.applicationSpecificPassword;
            const args = [
                "--upload-app",
                "-t",
                "ios",
                "-f",
                ipaFileLocation,
                "-u",
                data.credentials.username,
                "-p",
                password,
                "-k 100000",
            ];
            if (data.teamId) {
                args.push("--asc-provider");
                args.push(data.teamId);
            }
            if (data.verboseLogging) {
                args.push("--verbose");
            }
            yield this.$childProcess.spawnFromEvent(altoolPath, args, "close", {
                stdio: "inherit",
            });
        });
    }
    getBundleIdentifier(data) {
        return __awaiter(this, void 0, void 0, function* () {
            const { shouldExtractIpa, ipaFilePath } = data;
            if (shouldExtractIpa) {
                if (!this.$fs.exists(ipaFilePath) ||
                    path.extname(ipaFilePath) !== ".ipa") {
                    this.$errors.fail(`Cannot use specified ipa file ${ipaFilePath}. File either does not exist or is not an ipa file.`);
                }
                this.$logger.trace("--ipa set - extracting .ipa file to get app's bundle identifier");
                const destinationDir = yield this.$tempService.mkdirSync("ipa-");
                yield this.$fs.unzip(ipaFilePath, destinationDir);
                const payloadDir = path.join(destinationDir, "Payload");
                let allFiles = this.$fs.readDirectory(payloadDir);
                this.$logger.trace("ITMSTransporter .ipa Payload files:");
                allFiles.forEach((f) => this.$logger.trace(" - " + f));
                allFiles = allFiles.filter((f) => path.extname(f).toLowerCase() === ".app");
                if (allFiles.length > 1) {
                    this.$errors.fail("In the .ipa the ITMSTransporter is uploading there is more than one .app file. We don't know which one to upload.");
                }
                else if (allFiles.length <= 0) {
                    this.$errors.fail("In the .ipa the ITMSTransporter is uploading there must be at least one .app file.");
                }
                const appFile = path.join(payloadDir, allFiles[0]);
                const plistObject = yield this.$plistParser.parseFile(path.join(appFile, constants_1.INFO_PLIST_FILE_NAME));
                const bundleId = plistObject && plistObject.CFBundleIdentifier;
                if (!bundleId) {
                    this.$errors.fail(`Unable to determine bundle identifier from ${ipaFilePath}.`);
                }
                this.$logger.trace(`bundle identifier determined to be ${bundleId}`);
                return bundleId;
            }
            return this.$projectData.projectIdentifiers.ios;
        });
    }
    getAltoolPath() {
        return __awaiter(this, void 0, void 0, function* () {
            const xcodePath = yield this.$xcodeSelectService.getContentsDirectoryPath();
            let itmsTransporterPath = path.join(xcodePath, "..", "Contents", "Developer", "usr", "bin", constants_1.ITMSConstants.altoolExecutableName);
            return itmsTransporterPath;
        });
    }
    getITMSTransporterPath() {
        return __awaiter(this, void 0, void 0, function* () {
            const xcodePath = yield this.$xcodeSelectService.getContentsDirectoryPath();
            let itmsTransporterPath = path.join(xcodePath, "..", "Contents", "SharedFrameworks", "ContentDeliveryServices.framework", "Versions", "A", "itms", "bin", constants_1.ITMSConstants.iTMSExecutableName);
            const xcodeVersionData = yield this.$xcodeSelectService.getXcodeVersion();
            if (+xcodeVersionData.major < 11) {
                const loaderAppContentsPath = path.join(xcodePath, "Applications", "Application Loader.app", "Contents");
                itmsTransporterPath = path.join(loaderAppContentsPath, constants_1.ITMSConstants.iTMSDirectoryName, "bin", constants_1.ITMSConstants.iTMSExecutableName);
            }
            return itmsTransporterPath;
        });
    }
    getITMSMetadataXml(appleId, ipaFileName, ipaFileHash, ipaFileSize) {
        return `<?xml version="1.0" encoding="UTF-8"?>
<package version="software4.7" xmlns="http://apple.com/itunes/importer">
    <software_assets apple_id="${appleId}">
        <asset type="bundle">
            <data_file>
                <file_name>${ipaFileName}</file_name>
                <checksum type="md5">${ipaFileHash}</checksum>
                <size>${ipaFileSize}</size>
            </data_file>
        </asset>
    </software_assets>
</package>`;
    }
}
__decorate([
    (0, decorators_1.cache)()
], ITMSTransporterService.prototype, "getAltoolPath", null);
__decorate([
    (0, decorators_1.cache)()
], ITMSTransporterService.prototype, "getITMSTransporterPath", null);
exports.ITMSTransporterService = ITMSTransporterService;
yok_1.injector.register("itmsTransporterService", ITMSTransporterService);
//# sourceMappingURL=itmstransporter-service.js.map