"use strict";
/**
 * This is a utility file for docs library service that has functions to cater the services for
 * playbook adjacent collections.
 *
 * NOTE: 'PAC' in the filename stands for 'Playbook Adjacent Collections'
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.getModuleFqcnsUtils = exports.findModulesUtils = void 0;
const docsFinder_1 = require("../utils/docsFinder");
const docsParser_1 = require("../utils/docsParser");
const yaml_1 = require("../utils/yaml");
const playbookAdjacentPluginRouting = new Map();
async function findModulesUtils(playbookAdjacentCollectionsPath, searchText, context, contextPath, documentUri) {
    const playbookAdjacentModules = new Map();
    const playbookAdjacentModuleFqcns = new Set();
    const playbookAdjacentDocFragments = new Map();
    // find documentation for PAC
    (await (0, docsFinder_1.findDocumentation)(playbookAdjacentCollectionsPath, "collection")).forEach((doc) => {
        playbookAdjacentModules.set(doc.fqcn, doc);
        playbookAdjacentModuleFqcns.add(doc.fqcn);
    });
    (await (0, docsFinder_1.findDocumentation)(playbookAdjacentCollectionsPath, "collection_doc_fragment")).forEach((doc) => {
        playbookAdjacentDocFragments.set(doc.fqcn, doc);
    });
    (await (0, docsFinder_1.findPluginRouting)(playbookAdjacentCollectionsPath, "collection")).forEach((r, collection) => playbookAdjacentPluginRouting.set(collection, r));
    // add all valid redirect routes as possible FQCNs
    for (const [collection, routesByType] of playbookAdjacentPluginRouting) {
        for (const [name, route] of routesByType.get("modules") || []) {
            if (route.redirect && !route.tombstone) {
                playbookAdjacentModuleFqcns.add(`${collection}.${name}`);
            }
        }
    }
    // Now, start finding the module
    let hitFqcn;
    const candidateFqcns = await getCandidateFqcns(searchText, documentUri, contextPath, context);
    // check routing
    let moduleRoute;
    for (const fqcn of candidateFqcns) {
        moduleRoute = getModuleRoute(fqcn);
        if (moduleRoute) {
            hitFqcn = fqcn;
            break; // find first
        }
    }
    // find module
    let module;
    if (moduleRoute && moduleRoute.redirect) {
        module = playbookAdjacentModules.get(moduleRoute.redirect);
    }
    else {
        for (const fqcn of candidateFqcns) {
            module = playbookAdjacentModules.get(fqcn);
            if (module) {
                if (!hitFqcn) {
                    hitFqcn = fqcn;
                }
                break; // find first
            }
        }
    }
    if (module) {
        if (!module.fragments) {
            // collect information from documentation fragments
            (0, docsParser_1.processDocumentationFragments)(module, playbookAdjacentDocFragments);
        }
        if (!module.documentation) {
            // translate raw documentation into a typed structure
            module.documentation = (0, docsParser_1.processRawDocumentation)(module.rawDocumentationFragments);
        }
    }
    return [module, hitFqcn];
}
exports.findModulesUtils = findModulesUtils;
async function getModuleFqcnsUtils(playbookAdjacentCollectionsPath) {
    const playbookAdjacentModules = new Map();
    const playbookAdjacentModuleFqcns = new Set();
    const playbookAdjacentDocFragments = new Map();
    (await (0, docsFinder_1.findDocumentation)(playbookAdjacentCollectionsPath, "collection")).forEach((doc) => {
        playbookAdjacentModules.set(doc.fqcn, doc);
        playbookAdjacentModuleFqcns.add(doc.fqcn);
    });
    (await (0, docsFinder_1.findDocumentation)(playbookAdjacentCollectionsPath, "collection_doc_fragment")).forEach((doc) => {
        playbookAdjacentDocFragments.set(doc.fqcn, doc);
    });
    (await (0, docsFinder_1.findPluginRouting)(playbookAdjacentCollectionsPath, "collection")).forEach((r, collection) => playbookAdjacentPluginRouting.set(collection, r));
    // add all valid redirect routes as possible FQCNs
    for (const [collection, routesByType] of playbookAdjacentPluginRouting) {
        for (const [name, route] of routesByType.get("modules") || []) {
            if (route.redirect && !route.tombstone) {
                playbookAdjacentModuleFqcns.add(`${collection}.${name}`);
            }
        }
    }
    return playbookAdjacentModuleFqcns;
}
exports.getModuleFqcnsUtils = getModuleFqcnsUtils;
async function getCandidateFqcns(searchText, documentUri, contextPath, context) {
    const candidateFqcns = [];
    if (searchText.split(".").length >= 3) {
        candidateFqcns.push(searchText); // try searching as-is (FQCN match)
    }
    else {
        candidateFqcns.push(`ansible.builtin.${searchText}`); // try searching built-in
        if (documentUri) {
            const metadata = await context.documentMetadata.get(documentUri);
            if (metadata) {
                // try searching declared collections
                candidateFqcns.push(...metadata.collections.map((c) => `${c}.${searchText}`));
            }
        }
        if (contextPath) {
            candidateFqcns.push(...(0, yaml_1.getDeclaredCollections)(contextPath).map((c) => `${c}.${searchText}`));
        }
    }
    return candidateFqcns;
}
function getModuleRoute(fqcn) {
    const fqcn_array = fqcn.split(".");
    if (fqcn_array.length === 3) {
        const [namespace, collection, name] = fqcn_array;
        return playbookAdjacentPluginRouting
            .get(`${namespace}.${collection}`)
            ?.get("modules")
            ?.get(name);
    }
}
