"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildAndroid = void 0;
const tslib_1 = require("tslib");
const path_1 = tslib_1.__importDefault(require("path"));
const utils_1 = require("./utils");
const config_1 = require("./config");
const androidUtils_1 = require("./androidUtils");
const fs_1 = tslib_1.__importDefault(require("fs"));
const logger_1 = tslib_1.__importDefault(require("./logger"));
function capitalize(str) {
    return str.charAt(0).toUpperCase() + str.slice(1);
}
async function rebuildIncrementallyTheApk(apkPath, bundleOutput, resOutput, tempAssetBundle) {
    const tempDir = `${(0, utils_1.getRootDestinationFolder)()}/tmp_${(Math.random() * 1000).toFixed(0)}`;
    const tempApkDir = `${tempDir}/extracted_apk`;
    fs_1.default.mkdirSync(tempApkDir, { recursive: true });
    const newApkPath = path_1.default.join(tempDir, 'new_build.apk');
    const newSignedApkDir = path_1.default.join(tempDir, 'new_signed_apk');
    await (0, utils_1.executeCommandAsync)([(0, utils_1.getApkToolExecutable)(), 'd', apkPath, '-o', tempApkDir, '-f'].join(' '));
    if (!fs_1.default.existsSync(path_1.default.join(tempApkDir, 'assets'))) {
        fs_1.default.mkdirSync(path_1.default.join(tempApkDir, 'assets'));
    }
    // todo check bundle name
    await (0, utils_1.executeCommandAsync)(`cp -R ${tempAssetBundle}/* ${tempApkDir}/assets/`);
    await (0, utils_1.executeCommandAsync)(`cp -R ${tempAssetBundle}/res/* ${tempApkDir}/res/`);
    await (0, utils_1.executeCommandAsync)([(0, utils_1.getApkToolExecutable)(), 'b', tempApkDir, '-o', newApkPath].join(' '));
    /*
    params for the signature
         --ks c/Users/rams23/git/test/newRNApp/android/app/debug.keystore
     --ksAlias androiddebugkey
     --ksKeyPass android
     --ksPass android
     */
    // resign apk and align with uber-apk-signer
    await (0, utils_1.executeCommandAsync)(`java -jar ${(0, utils_1.getUberSignJava)()} \
     -a ${newApkPath} \
     -o ${newSignedApkDir}`);
    const apkFileName = fs_1.default.readdirSync(newSignedApkDir).find(f => f.endsWith('.apk'));
    if (!apkFileName) {
        throw new Error(`No apk found in the new signed apk folder ${newSignedApkDir}`);
    }
    const signedApkPath = path_1.default.join(newSignedApkDir, apkFileName);
    await (0, utils_1.executeCommandAsync)(`cp ${apkPath} ${apkPath.replace('.apk', '_old.apk')}`);
    await (0, utils_1.executeCommandAsync)(`cp ${signedApkPath} ${apkPath}`);
}
async function rebuildIncrementally(buildType, release = false) {
    const tempRNBundleDir = `${(0, utils_1.getRootDestinationFolder)()}/tmp_${(Math.random() * 1000).toFixed(0)}`;
    const tempAssetBundle = path_1.default.join(tempRNBundleDir, 'bundle_output');
    const bundleOutput = path_1.default.join(tempAssetBundle, 'index.android.bundle');
    const resOutput = path_1.default.join(tempAssetBundle, 'res');
    fs_1.default.mkdirSync(tempAssetBundle, { recursive: true });
    fs_1.default.mkdirSync(tempAssetBundle, { recursive: true });
    logger_1.default.info('Creating new bundle and assets');
    (0, utils_1.executeCommand)(`node ./node_modules/react-native/cli.js bundle \
    --platform android \
    --dev false \
    --entry-file ${(0, androidUtils_1.getAndroidIndexJsPath)()} \
    --bundle-output ${bundleOutput} \
    --assets-dest ${resOutput}`, { cwd: (0, utils_1.getProjectRootDir)() });
    logger_1.default.info('Rebuilding apks');
    const buildFolder = (0, androidUtils_1.getAppBuildFolder)(buildType, release);
    await Promise.all(fs_1.default
        .readdirSync(buildFolder)
        .filter(f => f.endsWith('.apk'))
        .map(async (apkFileName) => {
        if (apkFileName.endsWith('.apk')) {
            const apkPath = path_1.default.join(buildFolder, apkFileName);
            return rebuildIncrementallyTheApk(apkPath, bundleOutput, resOutput, tempAssetBundle);
        }
    }));
}
function getBuildTask(gradleFlavor, release) {
    const buildType = release ? 'Release' : 'Debug';
    const gradleBuildTask = gradleFlavor && gradleFlavor !== 'debug'
        ? `assemble${capitalize(gradleFlavor)}${buildType}`
        : `assemble${buildType}`;
    return gradleBuildTask;
}
async function buildAndroid(flavorName, incrementalBuild = false, release = false) {
    const buildFlavor = (0, config_1.getAndroidFlavors)(flavorName);
    if (!buildFlavor) {
        throw new Error(`No android flavor found for ${flavorName}`);
    }
    const { gradleFlavor } = buildFlavor;
    const androidFolder = path_1.default.join((0, utils_1.getProjectRootDir)(), 'android');
    if (incrementalBuild) {
        if (!(0, androidUtils_1.checkBuildPresent)(flavorName, release)) {
            throw new Error(`No build found for ${flavorName} ${release ? 'release' : 'debug'}. Unable to do incremental build`);
        }
        // create a temp directory
        await rebuildIncrementally(flavorName, release);
    }
    else {
        const gradleBuildTask = getBuildTask(gradleFlavor, release);
        (0, utils_1.executeCommand)(`${androidFolder}/gradlew \
      -Duser.dir=${androidFolder} \
      app:${gradleBuildTask} \
    `, { stdio: 'inherit' });
        const destinationDir = (0, androidUtils_1.getAppBuildFolder)(flavorName, release);
        const buildType = release ? 'release' : 'debug';
        (0, utils_1.executeCommand)(`rm -rf ${destinationDir} && mkdir -p ${destinationDir}`);
        const destinationFlavorFolder = gradleFlavor && gradleFlavor !== 'debug' ? `${gradleFlavor}/${buildType}` : buildType;
        const gradleOutputDir = `${androidFolder}/app/build/outputs/apk/${destinationFlavorFolder}/`;
        (0, utils_1.executeCommand)(`cp -R ${gradleOutputDir} ${destinationDir}`);
    }
}
exports.buildAndroid = buildAndroid;
