/**
 * Binding Registry - runtime registry of all loaded bindings
 * Supports simple (global/module) and hierarchical (namespace/type/member) formats
 *
 * This file is a thin facade. Heavy logic lives in:
 *   - binding-registry-resolution.ts  (member & extension-method resolution)
 *   - binding-registry-loading.ts     (addBindings ingestion)
 */
import { resolveLookupAlias, resolveMemberOverloads, resolveExtensionMethod, resolveExtensionMethodByKey, isTypeOrSubtype, } from "./binding-registry-resolution.js";
import { makeClrMemberKey } from "./binding-registry-loading.js";
import { addBindingsToState } from "./binding-registry-loading.js";
// ---------------------------------------------------------------------------
// Simple-binding helpers (used by getEmitterTypeMap and external callers)
// ---------------------------------------------------------------------------
export const simpleBindingContributesTypeIdentity = (descriptor) => {
    const explicit = descriptor.typeSemantics?.contributesTypeIdentity;
    if (explicit !== undefined) {
        return explicit;
    }
    return false;
};
const getSimpleBindingIdentityClrType = (descriptor) => descriptor.staticType ?? descriptor.type;
// ---------------------------------------------------------------------------
// BindingRegistry class (facade)
// ---------------------------------------------------------------------------
/**
 * Registry of all loaded bindings
 * Supports simple (global/module) and hierarchical (namespace/type/member) formats
 */
export class BindingRegistry {
    constructor() {
        this.loadedBindingFiles = new Set();
        this.sourceOwnedTypeAliases = new Set();
        // Simple format: global/module bindings for identifiers like console, Math, fs
        this.simpleBindings = new Map();
        this.simpleGlobalBindings = new Map();
        this.simpleModuleBindings = new Map();
        // Hierarchical format: namespace/type/member bindings
        this.namespaces = new Map();
        this.types = new Map(); // Flat lookup by TS name
        this.typeLookupAliasMap = new Map(); // CLR FQN or qualified TS alias -> canonical TS alias
        this.members = new Map(); // Flat lookup by "type.member"
        this.memberOverloads = new Map(); // Overload-aware lookup by "type.member"
        this.clrMemberOverloads = new Map(); // Overload-aware lookup by CLR target key
        this.clrTypeNamesByAlias = new Map();
        this.tsbindgenExports = new Map();
        this.tsSupertypes = new Map();
        this.tsBaseTypes = new Map();
        this.clrTypeNames = new Set();
        /**
         * Extension method index for instance-style calls.
         *
         * Keyed by:
         * - declaring namespace key (CLR namespace with '.' replaced by '_', e.g. "System_Linq")
         * - receiver TS type name (e.g. "IEnumerable_1")
         * - method TS name (e.g. "where")
         *
         * Values are one or more candidates (overloads share the same target).
         */
        this.extensionMethods = new Map();
    }
    /** Snapshot of mutable state for use by extracted pure resolution functions. */
    get state() {
        return {
            types: this.types,
            memberOverloads: this.memberOverloads,
            clrTypeNamesByAlias: this.clrTypeNamesByAlias,
            extensionMethods: this.extensionMethods,
            tsSupertypes: this.tsSupertypes,
            tsBaseTypes: this.tsBaseTypes,
            simpleBindings: this.simpleBindings,
            simpleGlobalBindings: this.simpleGlobalBindings,
            simpleModuleBindings: this.simpleModuleBindings,
            typeLookupAliasMap: this.typeLookupAliasMap,
            clrTypeNames: this.clrTypeNames,
        };
    }
    /**
     * Load a binding manifest file and add its bindings to the registry
     * Supports simple, full, and tsbindgen formats
     */
    addBindings(_filePath, manifest) {
        addBindingsToState({
            loadedBindingFiles: this.loadedBindingFiles,
            sourceOwnedTypeAliases: this.sourceOwnedTypeAliases,
            simpleBindings: this.simpleBindings,
            simpleGlobalBindings: this.simpleGlobalBindings,
            simpleModuleBindings: this.simpleModuleBindings,
            namespaces: this.namespaces,
            types: this.types,
            typeLookupAliasMap: this.typeLookupAliasMap,
            members: this.members,
            memberOverloads: this.memberOverloads,
            clrMemberOverloads: this.clrMemberOverloads,
            clrTypeNamesByAlias: this.clrTypeNamesByAlias,
            extensionMethods: this.extensionMethods,
            tsbindgenExports: this.tsbindgenExports,
            tsSupertypes: this.tsSupertypes,
            tsBaseTypes: this.tsBaseTypes,
            clrTypeNames: this.clrTypeNames,
        }, _filePath, manifest);
    }
    /**
     * Look up a simple global/module binding
     */
    getExactBinding(name) {
        return this.simpleBindings.get(name);
    }
    getExactBindingByKind(name, kind) {
        return kind === "global"
            ? this.simpleGlobalBindings.get(name)
            : this.simpleModuleBindings.get(name);
    }
    /**
     * Look up a simple global/module binding by exact authored name.
     */
    getBinding(name) {
        return this.simpleBindings.get(name);
    }
    getBindingByKind(name, kind) {
        return kind === "global"
            ? this.simpleGlobalBindings.get(name)
            : this.simpleModuleBindings.get(name);
    }
    hasSourceOwnedTypeAlias(typeAlias) {
        return this.sourceOwnedTypeAliases.has(typeAlias);
    }
    /**
     * Look up a namespace binding by TS alias
     */
    getNamespace(tsAlias) {
        return this.namespaces.get(tsAlias);
    }
    /**
     * Look up a type binding by TS alias
     */
    getType(tsAlias) {
        return this.types.get(resolveLookupAlias(this.state, tsAlias));
    }
    /**
     * Check whether a CLR type name exists in loaded bindings.
     */
    hasClrTypeName(clrTypeName) {
        return this.clrTypeNames.has(clrTypeName);
    }
    /**
     * Look up a member binding by TS type alias and member alias
     */
    getMember(typeAlias, memberAlias) {
        const overloads = this.getMemberOverloads(typeAlias, memberAlias);
        return overloads?.[0];
    }
    /**
     * Look up all member bindings for a TS type alias + member alias.
     *
     * IMPORTANT: Methods can be overloaded, and overloads can differ in ref/out/in
     * modifiers (tsbindgen provides these via `parameterModifiers`). This accessor
     * preserves overload sets so the call converter can select the correct one.
     */
    getMemberOverloads(typeAlias, memberAlias, preferredClrOwner) {
        return resolveMemberOverloads(this.state, typeAlias, memberAlias, preferredClrOwner);
    }
    /**
     * Look up all member bindings for a CLR member target.
     *
     * Keyed by declaring assembly, CLR type, and CLR member name.
     */
    getClrMemberOverloads(assembly, clrType, clrMember) {
        return this.clrMemberOverloads.get(makeClrMemberKey(assembly, clrType, clrMember));
    }
    /**
     * Resolve an extension method binding target by extension interface name.
     *
     * @param extensionInterfaceName - e.g. "__Ext_System_Linq_IEnumerable_1"
     * @param methodTsName - e.g. "where"
     */
    resolveExtensionMethod(extensionInterfaceName, methodTsName, callArgumentCount) {
        return resolveExtensionMethod(this.state, extensionInterfaceName, methodTsName, callArgumentCount);
    }
    /**
     * Resolve an extension method binding target by explicit (namespaceKey, receiverTypeName).
     *
     * Used when extension methods are emitted as method-table members with explicit `this:`
     * receiver constraints (the declaring interface name no longer encodes the receiver type).
     */
    resolveExtensionMethodByKey(namespaceKey, receiverTypeName, methodTsName, callArgumentCount) {
        return resolveExtensionMethodByKey(this.state, namespaceKey, receiverTypeName, methodTsName, callArgumentCount);
    }
    /**
     * Look up a tsbindgen flattened named export by CLR namespace + export name.
     */
    getTsbindgenExport(namespace, exportName) {
        return this.tsbindgenExports.get(namespace)?.get(exportName);
    }
    /**
     * Get all loaded simple bindings
     */
    getAllBindings() {
        return Array.from(this.simpleBindings.entries());
    }
    isTypeOrSubtype(typeAlias, superAlias) {
        return isTypeOrSubtype(this.state, typeAlias, superAlias);
    }
    /**
     * Get all loaded namespaces
     */
    getAllNamespaces() {
        return Array.from(this.namespaces.values());
    }
    /**
     * Get a copy of the types map for passing to the emitter.
     * Returns a new Map to ensure immutability - callers cannot modify the registry.
     */
    getTypesMap() {
        return new Map(this.types);
    }
    /**
     * Get the type map used by the emitter.
     *
     * This includes:
     * - hierarchical tsbindgen/full-manifest types
     * - simple global bindings that are type-like (e.g. Error, Date, Uint8Array)
     *
     * Expression lowering still uses the full binding registry. This view exists so
     * type emission can resolve ambient global constructors/types that are authored
     * via simple bindings instead of hierarchical type manifests.
     */
    getEmitterTypeMap() {
        const result = new Map(this.types);
        for (const [alias, descriptor] of this.simpleBindings) {
            if (!simpleBindingContributesTypeIdentity(descriptor)) {
                continue;
            }
            const identityClrType = getSimpleBindingIdentityClrType(descriptor);
            if (!result.has(alias)) {
                result.set(alias, {
                    alias,
                    name: identityClrType,
                    kind: "class",
                    members: [],
                });
            }
        }
        return result;
    }
    /**
     * Clear all loaded bindings
     */
    clear() {
        this.loadedBindingFiles.clear();
        this.simpleBindings.clear();
        this.simpleGlobalBindings.clear();
        this.simpleModuleBindings.clear();
        this.namespaces.clear();
        this.types.clear();
        this.typeLookupAliasMap.clear();
        this.members.clear();
        this.memberOverloads.clear();
        this.clrMemberOverloads.clear();
        this.clrTypeNamesByAlias.clear();
        this.extensionMethods.clear();
        this.tsbindgenExports.clear();
        this.tsSupertypes.clear();
        this.tsBaseTypes.clear();
        this.clrTypeNames.clear();
    }
}
//# sourceMappingURL=binding-registry.js.map