"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.writeProjectGraphReportToCache = writeProjectGraphReportToCache;
exports.getCurrentProjectGraphReport = getCurrentProjectGraphReport;
exports.getCurrentBuildFiles = getCurrentBuildFiles;
exports.populateProjectGraph = populateProjectGraph;
exports.processNxProjectGraph = processNxProjectGraph;
const node_fs_1 = require("node:fs");
const node_path_1 = require("node:path");
const devkit_1 = require("@nx/devkit");
const workspace_context_1 = require("nx/src/utils/workspace-context");
const split_config_files_1 = require("../../utils/split-config-files");
const cache_directory_1 = require("nx/src/utils/cache-directory");
const get_project_graph_lines_1 = require("./get-project-graph-lines");
const devkit_internals_1 = require("nx/src/devkit-internals");
function readProjectGraphReportCache(cachePath, hash) {
    const projectGraphReportCache = (0, node_fs_1.existsSync)(cachePath)
        ? (0, devkit_1.readJsonFile)(cachePath)
        : undefined;
    if (!projectGraphReportCache || projectGraphReportCache.hash !== hash) {
        return;
    }
    return projectGraphReportCache;
}
function writeProjectGraphReportToCache(cachePath, results) {
    let projectGraphReportJson = {
        hash: gradleCurrentConfigHash,
        ...results,
    };
    (0, devkit_1.writeJsonFile)(cachePath, projectGraphReportJson);
}
let projectGraphReportCache;
let gradleCurrentConfigHash;
let projectGraphReportCachePath = (0, node_path_1.join)(cache_directory_1.workspaceDataDirectory, 'gradle-nodes.hash');
function getCurrentProjectGraphReport() {
    if (!projectGraphReportCache) {
        throw new devkit_1.AggregateCreateNodesError([
            [
                null,
                new Error(`Expected cached gradle report. Please open an issue at https://github.com/nrwl/nx/issues/new/choose`),
            ],
        ], []);
    }
    return projectGraphReportCache;
}
function getCurrentBuildFiles() {
    const report = getCurrentProjectGraphReport();
    return report.buildFiles || [];
}
/**
 * This function populates the gradle report cache.
 * For each gradlew file, it runs the `nxProjectGraph` task and processes the output.
 * It will throw an error if both tasks fail.
 * It will accumulate the output of all gradlew files.
 * @param workspaceRoot
 * @param gradlewFiles absolute paths to all gradlew files in the workspace
 * @param options user specified gradle plugin options
 * @returns Promise<void>
 */
async function populateProjectGraph(workspaceRoot, gradlewFiles, options) {
    const gradleConfigHash = (0, devkit_1.hashArray)([
        await (0, workspace_context_1.hashWithWorkspaceContext)(workspaceRoot, [split_config_files_1.gradleConfigAndTestGlob]),
        (0, devkit_internals_1.hashObject)(options),
        process.env.CI,
    ]);
    projectGraphReportCache ??= readProjectGraphReportCache(projectGraphReportCachePath, gradleConfigHash);
    if (projectGraphReportCache &&
        (!gradleCurrentConfigHash || gradleConfigHash === gradleCurrentConfigHash)) {
        return;
    }
    const gradleProjectGraphReportStart = performance.mark('gradleProjectGraphReport:start');
    const projectGraphLines = await gradlewFiles.reduce(async (projectGraphLines, gradlewFile) => {
        const getNxProjectGraphLinesStart = performance.mark(`${gradlewFile}GetNxProjectGraphLines:start`);
        const allLines = await projectGraphLines;
        const currentLines = await (0, get_project_graph_lines_1.getNxProjectGraphLines)(gradlewFile, gradleConfigHash, options);
        const getNxProjectGraphLinesEnd = performance.mark(`${gradlewFile}GetNxProjectGraphLines:end`);
        performance.measure(`${gradlewFile}GetNxProjectGraphLines`, getNxProjectGraphLinesStart.name, getNxProjectGraphLinesEnd.name);
        return [...allLines, ...currentLines];
    }, Promise.resolve([]));
    const gradleProjectGraphReportEnd = performance.mark('gradleProjectGraphReport:end');
    performance.measure('gradleProjectGraphReport', gradleProjectGraphReportStart.name, gradleProjectGraphReportEnd.name);
    gradleCurrentConfigHash = gradleConfigHash;
    projectGraphReportCache = processNxProjectGraph(projectGraphLines);
    writeProjectGraphReportToCache(projectGraphReportCachePath, projectGraphReportCache);
}
function processNxProjectGraph(projectGraphLines) {
    let index = 0;
    let projectGraphReportForAllProjects = {
        nodes: {},
        dependencies: [],
        externalNodes: {},
    };
    const allBuildFiles = new Set();
    while (index < projectGraphLines.length) {
        const line = projectGraphLines[index].trim();
        if (line.startsWith('> Task ') && line.endsWith(':nxProjectGraph')) {
            while (index < projectGraphLines.length &&
                !projectGraphLines[index].includes('.json')) {
                index++;
            }
            const file = projectGraphLines[index];
            const projectGraphReportJson = (0, devkit_1.readJsonFile)(file);
            projectGraphReportForAllProjects.nodes = {
                ...projectGraphReportForAllProjects.nodes,
                ...projectGraphReportJson.nodes,
            };
            if (projectGraphReportJson.dependencies) {
                projectGraphReportForAllProjects.dependencies.push(...projectGraphReportJson.dependencies);
            }
            if (Object.keys(projectGraphReportJson.externalNodes ?? {}).length > 0) {
                projectGraphReportForAllProjects.externalNodes = {
                    ...projectGraphReportForAllProjects.externalNodes,
                    ...projectGraphReportJson.externalNodes,
                };
            }
            if (projectGraphReportJson.buildFiles) {
                projectGraphReportJson.buildFiles.forEach((buildFile) => allBuildFiles.add(buildFile));
            }
        }
        index++;
    }
    // Convert Set to array for the final result
    projectGraphReportForAllProjects.buildFiles = Array.from(allBuildFiles);
    return projectGraphReportForAllProjects;
}
