/**
 * Central registry of markwhen source factories.
 *
 * Each rApp that has date-bearing records registers a factory here.
 * The composite viewer (rSaga) and per-module timeline applets pull
 * from this registry.
 */

import type { MarkwhenSourceFactory, MwSource } from './types';
import { renderMarkwhen, type RenderOptions } from './projection';

const factories: Map<string, MarkwhenSourceFactory> = new Map();

export function registerMarkwhenSource(factory: MarkwhenSourceFactory): void {
	factories.set(factory.module, factory);
}

export function listMarkwhenSources(): MarkwhenSourceFactory[] {
	return [...factories.values()];
}

export function getMarkwhenSource(module: string): MarkwhenSourceFactory | undefined {
	return factories.get(module);
}

export interface ProjectOptions extends RenderOptions {
	/** Module ids to include. If omitted, projects all registered sources. */
	modules?: string[];
	from?: number;
	to?: number;
}

export async function projectSpace(space: string, opts: ProjectOptions = {}) {
	const chosen = opts.modules
		? opts.modules.map(m => factories.get(m)).filter((f): f is MarkwhenSourceFactory => !!f)
		: [...factories.values()];

	const sources: MwSource[] = [];
	for (const f of chosen) {
		try {
			const src = await f.build({ space, from: opts.from, to: opts.to });
			if (src && src.events.length > 0) sources.push(src);
		} catch (err) {
			console.warn(`[markwhen] source ${f.module} failed:`, err);
		}
	}
	return renderMarkwhen(sources, opts);
}
