"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PmdWrapperInvoker = void 0;
const node_path_1 = __importDefault(require("node:path"));
const node_fs_1 = __importDefault(require("node:fs"));
const code_analyzer_engine_api_1 = require("@salesforce/code-analyzer-engine-api");
const PMD_WRAPPER_JAVA_CLASS = "com.salesforce.sfca.pmdwrapper.PmdWrapper";
const PMD_WRAPPER_LIB_FOLDER = node_path_1.default.resolve(__dirname, '..', 'dist', 'java-lib');
const STDOUT_PROGRESS_MARKER = '[Progress]';
const STDOUT_ERROR_MARKER = '[Error] ';
class PmdWrapperInvoker {
    javaCommandExecutor;
    userProvidedJavaClasspathEntries;
    emitLogEvent;
    constructor(javaCommandExecutor, userProvidedJavaClasspathEntries, emitLogEvent) {
        this.javaCommandExecutor = javaCommandExecutor;
        this.userProvidedJavaClasspathEntries = userProvidedJavaClasspathEntries;
        this.emitLogEvent = emitLogEvent;
    }
    async invokeDescribeCommand(customRulesets, pmdRuleLanguageIds, workingFolder, emitProgress) {
        const pmdRulesOutputFile = node_path_1.default.join(workingFolder, 'ruleInfo.json');
        const customRulesetsListFile = node_path_1.default.join(workingFolder, 'customRulesetsList.txt');
        await node_fs_1.default.promises.writeFile(customRulesetsListFile, customRulesets.join('\n'), 'utf-8');
        emitProgress(10);
        const javaCmdArgs = [PMD_WRAPPER_JAVA_CLASS, 'describe', pmdRulesOutputFile, customRulesetsListFile, pmdRuleLanguageIds.join(',')];
        const javaClassPaths = [
            node_path_1.default.join(PMD_WRAPPER_LIB_FOLDER, '*'),
            ...this.userProvidedJavaClasspathEntries.map(toJavaClasspathEntry)
        ];
        await this.javaCommandExecutor.exec(javaCmdArgs, javaClassPaths, (stdOutMsg) => {
            if (stdOutMsg.startsWith(STDOUT_ERROR_MARKER)) {
                const errorMessage = stdOutMsg.slice(STDOUT_ERROR_MARKER.length).replaceAll('{NEWLINE}', '\n');
                throw new Error(errorMessage);
            }
            else {
                this.emitLogEvent(code_analyzer_engine_api_1.LogLevel.Fine, `[JAVA StdOut]: ${stdOutMsg}`);
            }
        });
        emitProgress(80);
        try {
            const pmdRulesFileContents = await node_fs_1.default.promises.readFile(pmdRulesOutputFile, 'utf-8');
            emitProgress(90);
            const pmdRuleInfoList = JSON.parse(pmdRulesFileContents);
            emitProgress(100);
            return pmdRuleInfoList;
        }
        catch (err) /* istanbul ignore next */ {
            const errMsg = err instanceof Error ? err.message : String(err);
            throw new Error((0, code_analyzer_engine_api_1.getMessageFromCatalog)(code_analyzer_engine_api_1.SHARED_MESSAGE_CATALOG, 'ErrorParsingOutputFile', pmdRulesOutputFile, errMsg), { cause: err });
        }
    }
    async invokeRunCommand(pmdRuleInfoList, runDataPerLanguage, workingFolder, emitProgress) {
        emitProgress(2);
        const ruleSetFileContents = createRuleSetFileContentsFor(pmdRuleInfoList);
        const ruleSetInputFile = node_path_1.default.join(workingFolder, 'ruleSetInputFile.xml');
        await node_fs_1.default.promises.writeFile(ruleSetInputFile, ruleSetFileContents, 'utf-8');
        emitProgress(6);
        const inputData = {
            ruleSetInputFile: ruleSetInputFile,
            runDataPerLanguage: runDataPerLanguage
        };
        const inputFile = node_path_1.default.join(workingFolder, 'pmdRunInput.json');
        await node_fs_1.default.promises.writeFile(inputFile, JSON.stringify(inputData), 'utf-8');
        emitProgress(10);
        const resultsOutputFile = node_path_1.default.join(workingFolder, 'resultsFile.json');
        const javaCmdArgs = [PMD_WRAPPER_JAVA_CLASS, 'run', inputFile, resultsOutputFile];
        const javaClassPaths = [
            node_path_1.default.join(PMD_WRAPPER_LIB_FOLDER, '*'),
            ...this.userProvidedJavaClasspathEntries.map(toJavaClasspathEntry)
        ];
        this.emitLogEvent(code_analyzer_engine_api_1.LogLevel.Fine, `Calling JAVA command with class path containing ${JSON.stringify(javaClassPaths)} and arguments: ${JSON.stringify(javaCmdArgs)}`);
        await this.javaCommandExecutor.exec(javaCmdArgs, javaClassPaths, (stdOutMsg) => {
            if (stdOutMsg.startsWith(STDOUT_PROGRESS_MARKER)) {
                const pmdWrapperProgress = parseFloat(stdOutMsg.slice(STDOUT_PROGRESS_MARKER.length));
                emitProgress(10 + 80 * (pmdWrapperProgress / 100)); // 10 to 90%
            }
            else {
                this.emitLogEvent(code_analyzer_engine_api_1.LogLevel.Fine, `[JAVA StdOut]: ${stdOutMsg}`);
            }
        });
        try {
            const resultsFileContents = await node_fs_1.default.promises.readFile(resultsOutputFile, 'utf-8');
            emitProgress(95);
            const pmdResults = JSON.parse(resultsFileContents);
            emitProgress(100);
            return pmdResults;
        }
        catch (err) /* istanbul ignore next */ {
            const errMsg = err instanceof Error ? err.message : String(err);
            throw new Error((0, code_analyzer_engine_api_1.getMessageFromCatalog)(code_analyzer_engine_api_1.SHARED_MESSAGE_CATALOG, 'ErrorParsingOutputFile', resultsOutputFile, errMsg), { cause: err });
        }
    }
}
exports.PmdWrapperInvoker = PmdWrapperInvoker;
function createRuleSetFileContentsFor(pmdRuleInfoList) {
    const ruleRefs = pmdRuleInfoList.map(pmdRuleInfo => `    <rule ref="${pmdRuleInfo.ruleSetFile}/${pmdRuleInfo.name}" />`);
    return '<?xml version="1.0" encoding="UTF-8"?>\n' +
        '<ruleset name="Ruleset for Salesforce Code Analyzer"\n' +
        '    xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"\n' +
        '    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n' +
        '    xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd">\n' +
        '    <description>Rules to Run for Salesforce Code Analyzer</description>\n' +
        ruleRefs.join('\n') + '\n' +
        '</ruleset>';
}
function toJavaClasspathEntry(jarfileOrFolder) {
    return jarfileOrFolder.toLowerCase().endsWith(".jar") ? jarfileOrFolder : jarfileOrFolder + node_path_1.default.sep + "*";
}
//# sourceMappingURL=pmd-wrapper.js.map