export class FactionEmblemProviderRegistry {
    static #providers = new Map();

    static register(definition = {}) {
        const id = String(definition.id || "").trim();
        const moduleId = String(definition.moduleId || "").trim();
        if (!id || !moduleId) throw new Error("Faction emblem providers require id and moduleId values.");
        if (typeof definition.getPresentation !== "function") throw new Error("Faction emblem providers require a getPresentation function.");
        const provider = {
            id,
            moduleId,
            priority: Number(definition.priority || 0),
            supports: typeof definition.supports === "function" ? definition.supports : () => false,
            getPresentation: definition.getPresentation,
            openEditor: typeof definition.openEditor === "function" ? definition.openEditor : null
        };
        this.#providers.set(id, provider);
        Hooks.callAll("augurNexusFactionEmblemProvidersChanged", { reason: "register", providerId: id, moduleId });
        return { id, moduleId };
    }

    static getProvider(entity = {}) {
        return [...this.#providers.values()]
            .sort((a, b) => b.priority - a.priority)
            .find(provider => {
                try {
                    return provider.supports(entity) === true;
                } catch (err) {
                    console.warn(`augur-nexus | Faction emblem provider ${provider.id} failed its support check.`, err);
                    return false;
                }
            }) || null;
    }

    static getPresentation(entity = {}) {
        const provider = this.getProvider(entity);
        if (!provider) return null;
        try {
            return this.#normalizePresentation(provider.getPresentation(entity), provider);
        } catch (err) {
            console.warn(`augur-nexus | Faction emblem provider ${provider.id} failed to resolve a presentation.`, err);
            return null;
        }
    }

    static openEditor(entity = {}, { onSelect = null } = {}) {
        const provider = this.getProvider(entity);
        if (!provider?.openEditor) return false;
        provider.openEditor({
            entity: foundry.utils.deepClone(entity),
            onSelect: selection => {
                if (typeof onSelect !== "function") return;
                return onSelect({
                    providerId: provider.id,
                    moduleId: provider.moduleId,
                    display: foundry.utils.deepClone(selection?.display || {}),
                    moduleData: foundry.utils.deepClone(selection?.moduleData || {})
                });
            }
        });
        return true;
    }

    static #normalizePresentation(presentation = {}, provider) {
        if (!presentation || typeof presentation !== "object") return null;
        const width = Math.max(1, Number(presentation.width || 1));
        const height = Math.max(1, Number(presentation.height || 1));
        const layers = (Array.isArray(presentation.layers) ? presentation.layers : []).map(layer => {
            const src = String(layer?.src || "").trim();
            if (!src) return null;
            return {
                src,
                x: Number(layer.x || 0),
                y: Number(layer.y || 0),
                width: Math.max(1, Number(layer.width || width)),
                height: Math.max(1, Number(layer.height || height))
            };
        }).filter(Boolean);
        if (!layers.length) return null;
        return {
            providerId: provider.id,
            moduleId: provider.moduleId,
            cacheKey: String(presentation.cacheKey || layers.map(layer => layer.src).join("|")),
            width,
            height,
            layers
        };
    }
}
