"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getAvailablePlatforms = void 0;
exports.expandPlatformExtensions = expandPlatformExtensions;
exports.getAvailablePlatformsUncached = getAvailablePlatformsUncached;
exports.platformExtensions = platformExtensions;
exports.parsePlatform = parsePlatform;
const package_1 = require("@rnx-kit/tools-node/package");
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const context_1 = require("./context");
/**
 * Returns a list of extensions that should be tried for the target platform in
 * prioritized order.
 * @param platform The platform to expand platform extensions for
 * @param extensions A list of extensions to expand
 * @returns A list of extensions
 */
function expandPlatformExtensions(platform, extensions) {
    const platforms = platformExtensions(platform);
    const expanded = platforms.reduce((expanded, platform) => {
        expanded.push(...extensions.map((ext) => `.${platform}${ext}`));
        return expanded;
    }, []);
    expanded.push(...extensions);
    return expanded;
}
/**
 * Returns a map of available React Native platforms.
 *
 * Note: This is used only when `@react-native-community/cli-config` is not
 * available. This function will be dropped when 0.68 is no longer supported.
 *
 * @param startDir The directory to look for react-native platforms from
 * @param platformMap A platform-to-npm-package map of known packages
 * @returns A platform-to-npm-package map, excluding "core" platforms.
 */
function getAvailablePlatformsCompat(startDir = process.cwd(), platformMap = { android: "", ios: "" }) {
    const packageJson = path.join(startDir, "package.json");
    if (!fs.existsSync(packageJson)) {
        const parent = path.dirname(startDir);
        return parent === startDir
            ? platformMap
            : getAvailablePlatformsUncached(path.dirname(startDir), platformMap);
    }
    const options = { startDir };
    const { dependencies, peerDependencies, devDependencies } = JSON.parse(fs.readFileSync(packageJson, { encoding: "utf-8" }));
    const packages = new Set(dependencies ? Object.keys(dependencies) : []);
    if (peerDependencies) {
        Object.keys(peerDependencies).forEach((pkg) => packages.add(pkg));
    }
    if (devDependencies) {
        Object.keys(devDependencies).forEach((pkg) => packages.add(pkg));
    }
    packages.forEach((pkgName) => {
        const pkgPath = (0, package_1.findPackageDependencyDir)(pkgName, options);
        if (!pkgPath) {
            return;
        }
        const configPath = path.join(pkgPath, "react-native.config.js");
        if (fs.existsSync(configPath)) {
            try {
                const { platforms } = require(configPath);
                if (platforms) {
                    Object.keys(platforms).forEach((platform) => {
                        if (typeof platformMap[platform] === "undefined") {
                            const { npmPackageName } = platforms[platform];
                            if (npmPackageName) {
                                platformMap[platform] = npmPackageName;
                            }
                        }
                    });
                }
            }
            catch (_) {
                // ignore
            }
        }
    });
    return platformMap;
}
/**
 * Returns a map of available React Native platforms. The result is cached.
 * @param startDir The directory to look for react-native platforms from
 * @returns A platform-to-npm-package map, excluding "core" platforms.
 */
exports.getAvailablePlatforms = (() => {
    let platformMap = undefined;
    return (startDir = process.cwd()) => {
        if (!platformMap) {
            try {
                platformMap = getAvailablePlatformsUncached(startDir);
            }
            catch (_) {
                // This only happens when `@react-native-community/cli-config` is not
                // available. This path may be dropped when 0.68 is no longer
                // supported.
                platformMap = getAvailablePlatformsCompat(startDir);
            }
        }
        return platformMap;
    };
})();
/**
 * Returns a map of available React Native platforms. The result is NOT cached.
 * @param startDir The directory to look for react-native platforms from
 * @param platformMap A platform-to-npm-package map of known packages
 * @returns A platform-to-npm-package map, excluding "core" platforms.
 */
function getAvailablePlatformsUncached(startDir = process.cwd(), platformMap = { android: "", ios: "" }) {
    const { platforms } = (0, context_1.loadContext)(startDir);
    if (typeof platforms === "object" && platforms) {
        for (const [name, info] of Object.entries(platforms)) {
            const { npmPackageName } = info;
            if (npmPackageName) {
                platformMap[name] = npmPackageName;
            }
        }
    }
    return platformMap;
}
/**
 * Returns file extensions that can be mapped to the target platform.
 * @param platform The platform to retrieve extensions for
 * @returns Valid extensions for specified platform
 */
function platformExtensions(platform) {
    switch (platform) {
        case "win32":
        case "windows":
            return [platform, "win", "native"];
        default:
            return [platform, "native"];
    }
}
/**
 * Parse a string to ensure it maps to a valid react-native platform.
 *
 * @param val Input string
 * @returns React-native platform name. Throws `Error` on failure.
 */
function parsePlatform(val) {
    switch (val) {
        case "android":
        case "ios":
        case "macos":
        case "win32":
        case "windows":
            return val;
        default:
            throw new Error("Invalid platform '" + val + "'");
    }
}
//# sourceMappingURL=platform.js.map