export type EventState = 'running' | 'countdown' | 'stopped' | 'unconfigured'; export interface EventStatePayload { state: EventState; serverNowUtc: string; eventStartUtc: string | null; eventEndUtc: string | null; secondsToStart: number | null; secondsToEnd: number | null; } export interface EventSourceLike { addEventListener( type: 'open' | 'message' | 'error' | 'unauthorized', listener: (ev: MessageEvent | Event) => void, ): void; close(): void; } export function formatDdHhMm(totalSeconds: number): string { if (!Number.isFinite(totalSeconds) || totalSeconds < 0) return '00:00:00'; const s = Math.floor(totalSeconds); const days = Math.floor(s / 86400); const hours = Math.floor((s % 86400) / 3600); const minutes = Math.floor((s % 3600) / 60); const pad = (n: number) => n.toString().padStart(2, '0'); return `${pad(days)}:${pad(hours)}:${pad(minutes)}`; } export function deriveCountdownText( state: EventState, secondsToStart: number | null, secondsToEnd: number | null, ): string { if (state === 'unconfigured') return ''; if (state === 'stopped') return 'Event ended'; if (state === 'countdown') { return secondsToStart == null ? '00:00:00' : formatDdHhMm(secondsToStart); } return secondsToEnd == null ? '00:00:00' : formatDdHhMm(secondsToEnd); } export const LED_COLOR_BY_STATE: Readonly> = { running: 'var(--color-success)', countdown: 'var(--color-warning)', stopped: 'var(--color-danger)', unconfigured: 'var(--color-secondary)', }; export function ledBackgroundColor(state: EventState): string { return LED_COLOR_BY_STATE[state]; }