import { type Creature, type CreatureId, EMPTY_UNDO_REDO_STATE, type Encounter, type PlayerCharacter, type UndoRedoState, } from "@initiative/domain"; import type { Adapters } from "../../contexts/adapter-context.js"; export function createTestAdapters(options?: { encounter?: Encounter | null; undoRedoState?: UndoRedoState; playerCharacters?: PlayerCharacter[]; creatures?: Map; sources?: Map< string, { displayName: string; creatures: Creature[]; cachedAt: number } >; }): Adapters { let storedEncounter = options?.encounter ?? null; let storedUndoRedo = options?.undoRedoState ?? EMPTY_UNDO_REDO_STATE; let storedPCs = options?.playerCharacters ?? []; const sourceStore = options?.sources ?? new Map< string, { displayName: string; creatures: Creature[]; cachedAt: number } >(); // Pre-populate sourceStore from creatures map if provided if (options?.creatures && !options?.sources) { // No-op: creatures are accessed directly from the map } const creatureMap = options?.creatures ?? new Map(); return { encounterPersistence: { load: () => storedEncounter, save: (e) => { storedEncounter = e; }, }, undoRedoPersistence: { load: () => storedUndoRedo, save: (state) => { storedUndoRedo = state; }, }, playerCharacterPersistence: { load: () => [...storedPCs], save: (pcs) => { storedPCs = pcs; }, }, bestiaryCache: { cacheSource(sourceCode, displayName, creatures) { sourceStore.set(sourceCode, { displayName, creatures, cachedAt: Date.now(), }); for (const c of creatures) { creatureMap.set(c.id, c); } return Promise.resolve(); }, isSourceCached(sourceCode) { return Promise.resolve(sourceStore.has(sourceCode)); }, getCachedSources() { return Promise.resolve( [...sourceStore.entries()].map(([sourceCode, info]) => ({ sourceCode, displayName: info.displayName, creatureCount: info.creatures.length, cachedAt: info.cachedAt, })), ); }, clearSource(sourceCode) { sourceStore.delete(sourceCode); return Promise.resolve(); }, clearAll() { sourceStore.clear(); return Promise.resolve(); }, loadAllCachedCreatures() { return Promise.resolve(new Map(creatureMap)); }, }, bestiaryIndex: { loadIndex: () => ({ sources: {}, creatures: [] }), getAllSourceCodes: () => [], getDefaultFetchUrl: (sourceCode, baseUrl) => { const filename = `bestiary-${sourceCode.toLowerCase()}.json`; if (baseUrl !== undefined) { const normalized = baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`; return `${normalized}${filename}`; } return `https://example.com/${filename}`; }, getSourceDisplayName: (sourceCode) => sourceCode, }, }; }