"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.executeTask = void 0;
const Log_1 = require("../core/Log");
const ClUtils_1 = require("./ClUtils");
const StorageUtilities_1 = require("../storage/StorageUtilities");
const NodeStorage_1 = require("../local/NodeStorage");
const IProjectInfoData_1 = require("../info/IProjectInfoData");
const worker_threads_1 = require("worker_threads");
const CartoApp_1 = require("../app/CartoApp");
const ProjectInfoSet_1 = require("../info/ProjectInfoSet");
const IInfoItemData_1 = require("../info/IInfoItemData");
const LocalEnvironment_1 = require("../local/LocalEnvironment");
const ProjectUtilities_1 = require("../app/ProjectUtilities");
const ZipStorage_1 = require("../storage/ZipStorage");
let carto;
let localEnv;
let outputStorage;
let outputStoragePath;
let activeContext;
async function executeTask(task) {
    if (!task.project) {
        Log_1.default.error("Could not find an associated project for the associated task.");
        return undefined;
    }
    activeContext = task.project?.ctorProjectName;
    if (localEnv === undefined) {
        localEnv = new LocalEnvironment_1.default(true);
    }
    localEnv.displayInfo = task.displayInfo;
    localEnv.displayVerbose = task.displayVerbose;
    if (carto === undefined) {
        CartoApp_1.default.hostType = CartoApp_1.HostType.toolsNodejs;
        carto = ClUtils_1.default.getCarto(localEnv);
        if (carto) {
            carto.onStatusAdded.subscribe(ClUtils_1.default.handleStatusAdded);
        }
    }
    if (!localEnv || !carto) {
        Log_1.default.error("Could not instantiate a local environment for the associated task.");
        return undefined;
    }
    if (!task.outputFolder) {
        outputStorage = undefined;
    }
    else if (task.outputFolder !== outputStoragePath) {
        outputStoragePath = task.outputFolder;
        outputStorage = new NodeStorage_1.default(task.outputFolder, "");
    }
    try {
        switch (task.task) {
            case ClUtils_1.TaskType.validate:
                return validate(carto, task.project, task.arguments["suite"], task.arguments["exclusionList"], task.arguments["outputMci"] === true, task.arguments["outputType"], task.displayInfo, task.force);
        }
    }
    catch (e) {
        return e.toString();
    }
    return undefined;
}
exports.executeTask = executeTask;
if (!worker_threads_1.isMainThread) {
    if (worker_threads_1.parentPort) {
        // Native Node.js worker_threads
        worker_threads_1.parentPort.on("message", async (task) => {
            try {
                const result = await executeTask(task);
                worker_threads_1.parentPort.postMessage(result);
            }
            catch (error) {
                worker_threads_1.parentPort.postMessage(error.toString());
            }
        });
    }
}
async function validate(carto, projectStart, suite, exclusionList, outputMci, outputType, displayInfo, force) {
    const project = ClUtils_1.default.createProject(carto, projectStart);
    project.readOnlySafety = true;
    let jsonFile;
    let jsonFileExists = false;
    if (outputStorage && outputType !== ClUtils_1.OutputType.noReports) {
        jsonFile = outputStorage.rootFolder.ensureFile(StorageUtilities_1.default.ensureFileNameIsSafe(StorageUtilities_1.default.getBaseFromName(project.containerName)) + ".mcr.json");
        jsonFileExists = await jsonFile.exists();
        if (jsonFileExists && !force && !displayInfo) {
            if (!jsonFile.isContentLoaded) {
                await jsonFile.loadContent(false);
            }
            let projectInfoData = StorageUtilities_1.default.getJsonObject(jsonFile);
            if (projectInfoData === undefined) {
                jsonFileExists = false;
            }
            else {
                let metaState = {
                    projectContainerName: project.containerName,
                    projectPath: project.projectFolder?.storageRelativePath,
                    projectName: project.name,
                    projectTitle: project.title,
                    infoSetData: projectInfoData,
                };
                project.dispose();
                return [metaState];
            }
        }
    }
    if (!jsonFileExists || force || displayInfo || outputType === ClUtils_1.OutputType.noReports) {
        return await validateAndDisposeProject(project, outputStorage, jsonFile, suite, exclusionList, outputMci, outputType);
    }
    else {
        Log_1.default.message("'" + project.name + "' has already been validated; skipping. Use --force to re-validate.");
    }
    return undefined;
}
async function validateAndDisposeProject(project, outputStorage, mcrJsonFile, suite, exclusionList, outputMci, outputType) {
    Log_1.default.verbose("Validating '" + project.name + "'" + (suite ? " with suite '" + suite + "'" : "") + ".");
    await project.inferProjectItemsFromFiles();
    let pis;
    let suiteInst;
    if (!suite && !exclusionList) {
        pis = project.indevInfoSet;
    }
    else {
        suiteInst = ProjectInfoSet_1.default.getSuiteFromString(suite ? suite : "default");
        pis = new ProjectInfoSet_1.default(project, suiteInst, exclusionList ? [exclusionList] : undefined);
    }
    await pis.generateForProject();
    const pisData = pis.getDataObject();
    const resultStates = [];
    const projectSet = {
        projectContainerName: project.containerName,
        projectPath: project.projectFolder?.storageRelativePath,
        projectName: project.name,
        projectTitle: project.title,
        infoSetData: pisData,
        suite: suiteInst,
    };
    resultStates.push(projectSet);
    pis.disconnectFromProject();
    if (localEnv?.displayInfo || localEnv?.displayVerbose) {
        let lastMessage;
        for (let k = 0; k < pis.items.length; k++) {
            const item = pis.items[k];
            const message = pis.itemToString(item);
            if (message !== lastMessage) {
                if ((localEnv.displayInfo || localEnv.displayVerbose) &&
                    item.itemType !== IInfoItemData_1.InfoItemType.info &&
                    item.itemType !== IInfoItemData_1.InfoItemType.featureAggregate) {
                    if (item.itemType === IInfoItemData_1.InfoItemType.error || item.itemType === IInfoItemData_1.InfoItemType.testCompleteFail) {
                        Log_1.default.error(message);
                        lastMessage = message;
                    }
                    else {
                        Log_1.default.message(message);
                        lastMessage = message;
                    }
                }
                else if (localEnv.displayVerbose) {
                    Log_1.default.verbose(message);
                    lastMessage = message;
                }
            }
        }
    }
    try {
        await outputResults(projectSet, pis, "", outputStorage, mcrJsonFile, outputMci, outputType);
    }
    catch (e) {
        Log_1.default.error(e);
    }
    // run derivative suites if no specific suite specified
    if (!suite || suite === "all") {
        const isAddon = await ProjectUtilities_1.default.getIsAddon(project);
        if (isAddon) {
            pis = new ProjectInfoSet_1.default(project, IProjectInfoData_1.ProjectInfoSuite.cooperativeAddOn);
            await pis.generateForProject();
            const projectSet = {
                projectContainerName: project.containerName,
                projectPath: project.projectFolder?.storageRelativePath,
                projectName: project.name,
                projectTitle: project.title,
                infoSetData: pis.getDataObject(),
                suite: IProjectInfoData_1.ProjectInfoSuite.cooperativeAddOn,
            };
            resultStates.push(projectSet);
            await outputResults(projectSet, pis, "addon", outputStorage, undefined);
        }
        pis = new ProjectInfoSet_1.default(project, IProjectInfoData_1.ProjectInfoSuite.sharing);
        await pis.generateForProject();
        const projectSet = {
            projectContainerName: project.containerName,
            projectPath: project.projectFolder?.storageRelativePath,
            projectName: project.name,
            projectTitle: project.title,
            infoSetData: pis.getDataObject(),
            suite: IProjectInfoData_1.ProjectInfoSuite.sharing,
        };
        resultStates.push(projectSet);
        await outputResults(projectSet, pis, "sharing", outputStorage, undefined);
        const shouldRunPlatformVersion = pisData.info["CWave"] !== undefined;
        if (shouldRunPlatformVersion) {
            pis = new ProjectInfoSet_1.default(project, IProjectInfoData_1.ProjectInfoSuite.currentPlatformVersions);
            await pis.generateForProject();
            const projectSet = {
                projectContainerName: project.containerName,
                projectPath: project.projectFolder?.storageRelativePath,
                projectName: project.name,
                projectTitle: project.title,
                infoSetData: pis.getDataObject(),
                suite: IProjectInfoData_1.ProjectInfoSuite.currentPlatformVersions,
            };
            resultStates.push(projectSet);
            await outputResults(projectSet, pis, "currentplatform", outputStorage, undefined);
        }
    }
    project.dispose();
    return resultStates;
}
async function outputResults(projectSet, pis, fileNameModifier, outputStorage, mcrJsonFile, outputMci, outputType) {
    if (outputStorage) {
        if (outputType !== ClUtils_1.OutputType.noReports) {
            const reportHtmlFile = outputStorage.rootFolder.ensureFile(StorageUtilities_1.default.ensureFileNameIsSafe(StorageUtilities_1.default.getBaseFromName(projectSet.projectContainerName)) +
                fileNameModifier +
                ".report.html");
            const reportContent = pis.getReportHtml(projectSet.projectName, projectSet.projectPath, undefined);
            reportHtmlFile.setContent(reportContent);
            reportHtmlFile.saveContent();
        }
        if (outputMci) {
            const indexFolder = outputStorage.rootFolder.ensureFolder("mci");
            const hashCatalogFolder = outputStorage.rootFolder.ensureFolder("mch");
            await indexFolder.ensureExists();
            await hashCatalogFolder.ensureExists();
            const mciContentFile = indexFolder.ensureFile(StorageUtilities_1.default.ensureFileNameIsSafe(StorageUtilities_1.default.getBaseFromName(projectSet.projectContainerName)) +
                fileNameModifier +
                ".mci.json");
            const mchContentFile = hashCatalogFolder.ensureFile(StorageUtilities_1.default.ensureFileNameIsSafe(StorageUtilities_1.default.getBaseFromName(projectSet.projectContainerName)) +
                fileNameModifier +
                ".mch.json");
            if (outputType === ClUtils_1.OutputType.noReports) {
                mciContentFile.setContent(pis.getStrictIndexJson(projectSet.projectName, projectSet.projectPath, undefined));
            }
            else {
                mciContentFile.setContent(pis.getIndexJson(projectSet.projectName, projectSet.projectPath, undefined));
            }
            mciContentFile.saveContent();
            const hashCatalogContent = pis.getHashCatalogJson();
            mchContentFile.setContent(hashCatalogContent);
            mchContentFile.saveContent();
            const mciContentFileZip = indexFolder.ensureFile(StorageUtilities_1.default.ensureFileNameIsSafe(StorageUtilities_1.default.getBaseFromName(projectSet.projectContainerName)) +
                fileNameModifier +
                ".mci.json.zip");
            let contentStr = "";
            if (outputType === ClUtils_1.OutputType.noReports) {
                contentStr = pis.getStrictIndexJson(projectSet.projectName, projectSet.projectPath, undefined);
            }
            else {
                contentStr = pis.getIndexJson(projectSet.projectName, projectSet.projectPath, undefined);
            }
            mciContentFile.setContent(contentStr);
            mciContentFile.saveContent();
            const zs = ZipStorage_1.default.fromJsonString(contentStr);
            const contentBytes = await zs.generateUint8ArrayAsync();
            mciContentFileZip.setContent(contentBytes);
            mciContentFileZip.saveContent();
        }
        if (outputType !== ClUtils_1.OutputType.noReports) {
            const csvFile = outputStorage.rootFolder.ensureFile(StorageUtilities_1.default.ensureFileNameIsSafe(StorageUtilities_1.default.getBaseFromName(projectSet.projectContainerName)) +
                fileNameModifier +
                ".csv");
            const pisLines = pis.getItemCsvLines();
            const csvContent = ProjectInfoSet_1.default.CommonCsvHeader + "\n" + pisLines.join("\n");
            csvFile.setContent(csvContent);
            csvFile.saveContent();
        }
        if (mcrJsonFile) {
            if (projectSet.infoSetData.index) {
                projectSet.infoSetData.index = undefined;
            }
            const mcrContent = JSON.stringify(projectSet.infoSetData, null, 2);
            mcrJsonFile.setContent(mcrContent);
            mcrJsonFile.saveContent();
        }
    }
}

//# sourceMappingURL=../maps/cli/TaskWorker.js.map
