"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.cancelPendingProjectGraphRequest = cancelPendingProjectGraphRequest;
exports.getGraphTimeoutMs = getGraphTimeoutMs;
exports.getNxProjectGraphLines = getNxProjectGraphLines;
const devkit_1 = require("@nx/devkit");
const devkit_internals_1 = require("nx/src/devkit-internals");
const exec_gradle_1 = require("../../utils/exec-gradle");
const DEFAULT_GRAPH_TIMEOUT_SECONDS = (0, devkit_internals_1.isCI)() ? 600 : 120;
let currentAbortController;
/**
 * Cancel any in-flight Gradle project graph process.
 * Safe to call even if nothing is running.
 */
function cancelPendingProjectGraphRequest() {
    if (currentAbortController) {
        currentAbortController.abort('cancelled');
        currentAbortController = undefined;
    }
}
function getGraphTimeoutMs() {
    const envTimeout = process.env.NX_GRADLE_PROJECT_GRAPH_TIMEOUT;
    if (envTimeout) {
        const parsed = Number(envTimeout);
        if (!Number.isNaN(parsed) && parsed > 0) {
            return parsed * 1000;
        }
    }
    return DEFAULT_GRAPH_TIMEOUT_SECONDS * 1000;
}
async function getNxProjectGraphLines(gradlewFile, gradleConfigHash, gradlePluginOptions) {
    let nxProjectGraphBuffer;
    const gradlePluginOptionsArgs = Object.entries(gradlePluginOptions ?? {})?.map(([key, value]) => `-P${key}=${value}`) ?? [];
    const timeoutMs = getGraphTimeoutMs();
    const timeoutSeconds = timeoutMs / 1000;
    // Cancel any in-flight Gradle process from a previous call, then create a fresh controller.
    cancelPendingProjectGraphRequest();
    const controller = new AbortController();
    currentAbortController = controller;
    const signal = controller.signal;
    const timer = setTimeout(() => controller.abort(), timeoutMs);
    try {
        nxProjectGraphBuffer = await (0, exec_gradle_1.execGradleAsync)(gradlewFile, [
            'nxProjectGraph',
            `-Phash=${gradleConfigHash}`,
            '--no-configuration-cache', // disable configuration cache
            '--parallel', // add parallel to improve performance
            '--build-cache', // enable build cache
            '--warning-mode',
            'none',
            ...gradlePluginOptionsArgs,
            `-PworkspaceRoot=${devkit_1.workspaceRoot}`,
            process.env.NX_GRADLE_VERBOSE_LOGGING ? '--info' : '',
        ], { signal });
    }
    catch (e) {
        // Cancelled by a newer populateProjectGraph call — let the caller handle it
        if (signal.reason === 'cancelled') {
            throw new Error('Gradle project graph generation was cancelled');
        }
        if (signal.aborted) {
            throw new devkit_1.AggregateCreateNodesError([
                [
                    gradlewFile,
                    new Error(`Gradle project graph generation timed out after ${timeoutSeconds} ${timeoutSeconds === 1 ? 'second' : 'seconds'}.\n` +
                        `  1. Run "gradlew --stop" to stop the Gradle daemon, then run "gradlew clean" to clear the build cache.\n` +
                        `  2. If the issue persists, set the environment variable NX_GRADLE_PROJECT_GRAPH_TIMEOUT to a higher value (in seconds) to increase the timeout.\n` +
                        `  3. If the issue still persists, set NX_GRADLE_DISABLE=true to disable the Gradle plugin entirely.`),
                ],
            ], []);
        }
        else if (e.toString()?.includes('ERROR: JAVA_HOME')) {
            throw new devkit_1.AggregateCreateNodesError([
                [
                    gradlewFile,
                    new Error(`Could not find Java. Please install Java and try again: https://www.java.com/en/download/help/index_installing.html.\n\r${e.toString()}`),
                ],
            ], []);
        }
        else if (e.toString()?.includes(`Task 'nxProjectGraph' not found`)) {
            throw new devkit_1.AggregateCreateNodesError([
                [
                    gradlewFile,
                    new Error(`Could not run 'nxProjectGraph' task. Please run 'nx generate @nx/gradle:init' to add the necessary plugin dev.nx.gradle.project-graph.\n\r${e.toString()}`),
                ],
            ], []);
        }
        else {
            throw new devkit_1.AggregateCreateNodesError([
                [
                    gradlewFile,
                    new Error(`Could not run 'nxProjectGraph' Gradle task. Please install Gradle and try again: https://gradle.org/install/.\r\n${e.toString()}`),
                ],
            ], []);
        }
    }
    finally {
        clearTimeout(timer);
    }
    const projectGraphLines = nxProjectGraphBuffer
        .toString()
        .split(exec_gradle_1.newLineSeparator)
        .filter((line) => line.trim() !== '');
    if (process.env.NX_VERBOSE_LOGGING === 'true') {
        devkit_1.output.log({
            title: `Successfully ran 'nxProjectGraph' task using ${gradlewFile} with hash ${gradleConfigHash}`,
            bodyLines: projectGraphLines,
        });
    }
    return projectGraphLines;
}
