"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.runApp = exports.findBestApkInFolder = void 0;
const tslib_1 = require("tslib");
const child_process_1 = tslib_1.__importStar(require("child_process"));
const fs_1 = tslib_1.__importDefault(require("fs"));
const utils_1 = require("./utils");
const listAndroidDevices_1 = tslib_1.__importDefault(require("@react-native-community/cli-platform-android/build/commands/runAndroid/listAndroidDevices"));
const tryRunAdbReverse_1 = tslib_1.__importDefault(require("@react-native-community/cli-platform-android/build/commands/runAndroid/tryRunAdbReverse"));
const adb_1 = tslib_1.__importDefault(require("@react-native-community/cli-platform-android/build/commands/runAndroid/adb"));
const getAdbPath_1 = tslib_1.__importDefault(require("@react-native-community/cli-platform-android/build/commands/runAndroid/getAdbPath"));
const tryLaunchEmulator_1 = tslib_1.__importDefault(require("@react-native-community/cli-platform-android/build/commands/runAndroid/tryLaunchEmulator"));
const buildAndroid_1 = require("./buildAndroid");
const androidUtils_1 = require("./androidUtils");
const path_1 = tslib_1.__importDefault(require("path"));
const logger_1 = tslib_1.__importDefault(require("./logger"));
function getAdbPath() {
    const androidHome = process.env.ANDROID_HOME;
    if (!androidHome) {
        throw new Error('ANDROID_HOME is not set');
    }
    return (0, getAdbPath_1.default)();
}
async function getDevices() {
    return (0, listAndroidDevices_1.default)();
}
function getBootedDevices() {
    const output = child_process_1.default.execSync(`${getAdbPath()} devices | tail -n +2 | cut -sf 1`);
    return String(output).trim().split('\n');
}
function findBestApkInFolder(dir, arc) {
    const files = fs_1.default.readdirSync(dir);
    // todo debug
    const singleApkFound = files.find(f => f === 'app-debug.apk');
    if (singleApkFound) {
        return path_1.default.join(dir, 'app-debug.apk');
    }
    else {
        if (arc) {
            const apkForArc = files.find(f => f.includes(arc));
            if (apkForArc) {
                return path_1.default.join(dir, apkForArc);
            }
            else {
                throw Error('Unable to find correct apk in' + dir);
            }
        }
        else {
            throw Error('Unable to find correct apk in' + dir);
        }
    }
}
exports.findBestApkInFolder = findBestApkInFolder;
function installApp(device, engineDir, buildType) {
    const appDir = (0, androidUtils_1.getAppBuildFolder)(buildType);
    const cpu = adb_1.default.getCPU(getAdbPath(), device);
    const apkPath = findBestApkInFolder(appDir, cpu || undefined);
    (0, child_process_1.execSync)(`${getAdbPath()} -s ${device} install -r ${apkPath}`);
}
function launchApp(device, packageId) {
    (0, child_process_1.execSync)(`${getAdbPath()} -s ${device} shell monkey -p ${packageId} -c android.intent.category.LAUNCHER 1`);
}
async function getAvailableDevicePort(port = 5552) {
    const devices = adb_1.default.getDevices(getAdbPath());
    if (port > 5682) {
        throw new Error('Failed to launch emulator...');
    }
    if (devices.some(d => d.includes(port.toString()))) {
        return await getAvailableDevicePort(port + 2);
    }
    return port;
}
function getBundleIdentifier(appBuildFolder) {
    var _a;
    if (fs_1.default.existsSync(path_1.default.join(appBuildFolder, 'output-metadata.json'))) {
        const id = (_a = JSON.parse(fs_1.default.readFileSync(path_1.default.join(appBuildFolder, 'output-metadata.json'), 'utf-8'))) === null || _a === void 0 ? void 0 : _a.applicationId;
        if (id) {
            return id;
        }
    }
    // todo improve bundle id identifier
    return 'todo';
}
function installAndLaunch(port, deviceId, buildType, appIdentifier) {
    (0, tryRunAdbReverse_1.default)(port, deviceId);
    logger_1.default.info('Installing app...');
    installApp(deviceId, (0, utils_1.getProjectRootDir)(), buildType);
    logger_1.default.info('Launching app...');
    launchApp(deviceId, appIdentifier);
}
async function runApp(buildFlavor, port = '8081') {
    if (!(0, androidUtils_1.checkBuildPresent)(buildFlavor)) {
        logger_1.default.info('Build not present, starting build');
        await (0, buildAndroid_1.buildAndroid)(buildFlavor);
    }
    else {
        logger_1.default.info('Build already present, skipping build');
    }
    // todo improvement: if there is only one device, use it directly
    const device = await (0, listAndroidDevices_1.default)();
    const appIdentifier = getBundleIdentifier((0, androidUtils_1.getAppBuildFolder)(buildFlavor));
    if (!device) {
        throw new Error('No android devices available');
    }
    else {
        if (device.connected) {
            installAndLaunch(port, device.deviceId, buildFlavor, appIdentifier);
        }
        else {
            const newEmulatorPort = await getAvailableDevicePort();
            const emulator = `emulator-${newEmulatorPort}`;
            const result = await (0, tryLaunchEmulator_1.default)(getAdbPath(), device.readableName, newEmulatorPort);
            if (result.success) {
                installAndLaunch(port, emulator, buildFlavor, appIdentifier);
            }
        }
    }
}
exports.runApp = runApp;
