import type { AppRegistryMap, AppRegistryEntry } from '../../components/Workspace';
import { useGlobal } from 'hooks/useGlobal';

export type AppRegistryMeta = { key: string } & AppRegistryEntry;

const EMPTY_REGISTRY: AppRegistryMap = {};

/**
 * Read the app registry. It is written once, by `seedAppRegistry`, before anything renders — there is no
 * `registerApp` any more because nothing ever called one, and a registry that can be added to at runtime
 * is a registry whose contents depend on what has mounted so far.
 */
export function useAppRegistry() {
  const [registry] = useGlobal<AppRegistryMap>('APP_REGISTRY', EMPTY_REGISTRY);
  return { registry };
}

export type UseAppRegistryType = ReturnType<typeof useAppRegistry>;

export const findDuplicateKeys = (metas: AppRegistryMeta[]): string[] => [
  ...new Set(metas.map((m) => m.key).filter((key, i, keys) => keys.indexOf(key) !== i)),
];

/**
 * A collision here last-wins silently: one app stops existing, and every panel already holding its
 * `appType` renders the other app's component instead. It is an authoring mistake, so it is caught by a
 * test over the real meta list (`AppRegistry.test.ts`) rather than by throwing — a duplicate key is not a
 * reason to take the owner's dashboard down at runtime.
 */
export const metasToRegistry = (metas: AppRegistryMeta[]): AppRegistryMap => {
  const duplicates = findDuplicateKeys(metas);
  if (duplicates.length > 0)
    console.error(`AppRegistry: duplicate app key(s) ${duplicates.join(', ')} — one app is unreachable`);

  return Object.fromEntries(metas.map(({ key, ...entry }) => [key, entry]));
};
