/**
 * Dynamic shape registry — replaces the 300-line switch in canvas.html
 * and the 165-line if-chain in community-sync.ts.
 *
 * Each shape class registers itself with `fromData()` and `applyData()`,
 * so creation and sync are fully data-driven.
 */

import type { FolkShape } from "./folk-shape";
import type { ShapeData } from "./community-sync";

export interface ShapeRegistration {
	tagName: string;
	/** The custom element class (must have fromData/applyData) */
	elementClass: typeof HTMLElement & {
		fromData?(data: ShapeData): HTMLElement;
	};
}

class ShapeRegistry {
	#registrations = new Map<string, ShapeRegistration>();
	#moduleMap = new Map<string, string>();

	/** Register a shape type. */
	register(tagName: string, elementClass: ShapeRegistration["elementClass"]): void {
		this.#registrations.set(tagName, { tagName, elementClass });
	}

	/** Associate a shape tag with a module ID. */
	setModule(tagName: string, moduleId: string): void {
		this.#moduleMap.set(tagName, moduleId);
	}

	/** Get the owning module ID for a shape tag, or undefined if core/always-available. */
	moduleOf(tagName: string): string | undefined {
		return this.#moduleMap.get(tagName);
	}

	/** Get registration for a tag name. */
	getRegistration(tagName: string): ShapeRegistration | undefined {
		return this.#registrations.get(tagName);
	}

	/** Create a new element from ShapeData using the class's static fromData(). */
	createElement(data: ShapeData): HTMLElement | null {
		const reg = this.#registrations.get(data.type);
		if (!reg) return null;

		if (typeof reg.elementClass.fromData === "function") {
			return reg.elementClass.fromData(data);
		}

		// Fallback: basic createElement
		const el = document.createElement(data.type);
		el.id = data.id;
		return el;
	}

	/** Update an existing element using its instance applyData(). */
	updateElement(shape: any, data: ShapeData): void {
		if (typeof shape.applyData === "function") {
			shape.applyData(data);
		}
	}

	/** List all registered tag names. */
	listAll(): string[] {
		return Array.from(this.#registrations.keys());
	}

	/** Check if a type is registered. */
	has(tagName: string): boolean {
		return this.#registrations.has(tagName);
	}
}

/** Singleton registry instance. */
export const shapeRegistry = new ShapeRegistry();
