import type { ConditionId } from "./conditions.js"; import { CONDITION_DEFINITIONS, VALID_CONDITION_IDS } from "./conditions.js"; import type { DomainEvent } from "./events.js"; import type { CombatantId, DomainError, Encounter } from "./types.js"; export interface ToggleConditionSuccess { readonly encounter: Encounter; readonly events: DomainEvent[]; } export function toggleCondition( encounter: Encounter, combatantId: CombatantId, conditionId: ConditionId, ): ToggleConditionSuccess | DomainError { if (!VALID_CONDITION_IDS.has(conditionId)) { return { kind: "domain-error", code: "unknown-condition", message: `Unknown condition "${conditionId}"`, }; } const targetIdx = encounter.combatants.findIndex((c) => c.id === combatantId); if (targetIdx === -1) { return { kind: "domain-error", code: "combatant-not-found", message: `No combatant found with ID "${combatantId}"`, }; } const target = encounter.combatants[targetIdx]; const current = target.conditions ?? []; const isActive = current.includes(conditionId); let newConditions: readonly ConditionId[] | undefined; let event: DomainEvent; if (isActive) { const filtered = current.filter((c) => c !== conditionId); newConditions = filtered.length > 0 ? filtered : undefined; event = { type: "ConditionRemoved", combatantId, condition: conditionId }; } else { const added = [...current, conditionId]; const order = CONDITION_DEFINITIONS.map((d) => d.id); added.sort((a, b) => order.indexOf(a) - order.indexOf(b)); newConditions = added; event = { type: "ConditionAdded", combatantId, condition: conditionId }; } const updatedCombatants = encounter.combatants.map((c) => c.id === combatantId ? { ...c, conditions: newConditions } : c, ); return { encounter: { combatants: updatedCombatants, activeIndex: encounter.activeIndex, roundNumber: encounter.roundNumber, }, events: [event], }; }