import { parseCrossProtocolRef } from '@enbox/dwn-sdk-js';
import { lexicographicalCompare } from './types/sync.js';
/**
 * Extracts the protocol-level closure edges a retained protocol definition can
 * introduce for sync registration validation.
 */
export function getProtocolClosureEdges(definition) {
    var _a;
    const usesProtocols = sortedUnique(Object.values((_a = definition.uses) !== null && _a !== void 0 ? _a : {}));
    const dependencyProtocols = sortedUnique(collectDependencyProtocols(definition));
    return { dependencyProtocols, usesProtocols };
}
function collectDependencyProtocols(definition) {
    var _a;
    const protocols = [];
    for (const ruleSet of Object.values(definition.structure)) {
        collectDependencyProtocolsFromRuleSet(ruleSet, (_a = definition.uses) !== null && _a !== void 0 ? _a : {}, protocols);
    }
    return protocols;
}
function collectDependencyProtocolsFromRuleSet(ruleSet, uses, protocols) {
    var _a;
    collectReferencedProtocol(ruleSet.$ref, uses, protocols);
    for (const actionRule of (_a = ruleSet.$actions) !== null && _a !== void 0 ? _a : []) {
        collectReferencedProtocol(actionRule.role, uses, protocols);
        collectReferencedProtocol(actionRule.of, uses, protocols);
    }
    for (const [key, value] of Object.entries(ruleSet)) {
        if (key.startsWith('$') || !isProtocolRuleSet(value)) {
            continue;
        }
        collectDependencyProtocolsFromRuleSet(value, uses, protocols);
    }
}
function collectReferencedProtocol(ref, uses, protocols) {
    if (ref === undefined) {
        return;
    }
    const parsed = parseCrossProtocolRef(ref);
    if (parsed === undefined) {
        return;
    }
    const protocol = uses[parsed.alias];
    if (protocol !== undefined) {
        protocols.push(protocol);
    }
}
function isProtocolRuleSet(value) {
    return typeof value === 'object' && value !== null && !Array.isArray(value);
}
function sortedUnique(values) {
    return [...new Set(values)].sort(lexicographicalCompare);
}
//# sourceMappingURL=sync-scope-closure.js.map