// SPDX-FileCopyrightText: 2026 Stan Grams <sjg@haxx.space>
//
// SPDX-License-Identifier: GPL-2.0-or-later

// Typed view of the `window.trx` host contract for lazy feature bundles.
//
// Feature entries are separate esbuild bundles, so they cannot share module
// instances with the application entry and must reach application state and
// services through the host namespace documented in
// `docs/frontend-architecture.md`.  Declaring that contract once here keeps the
// feature bundles from re-deriving it — and from drifting back to bare `window`
// properties, which the module graph no longer publishes.

export interface HostDecoderDescriptor {
  id: string;
  label: string;
  activation?: string;
  active_modes?: string[];
  bookmark_selectable?: boolean;
}

export interface HostState {
  readonly serverLat: number | null;
  readonly serverLon: number | null;
  readonly authEnabled: boolean;
  readonly authRole: string | null;
  readonly lastActiveRigId: string | null;
  readonly lastRigIds: string[];
  readonly lastRigDisplayNames: Record<string, string>;
  readonly lastFreqHz: number | null;
  readonly lastSpectrumData: { sample_rate: number; center_hz: number } | null;
  readonly jogUnit: number;
  readonly rxActive: boolean;
  readonly decoderRegistry: readonly HostDecoderDescriptor[];
  lastModeName: string;
  currentBandwidthHz: number;
  audioChannelOverride: string | null;
}

export interface HostCore {
  postPath(path: string): Promise<unknown>;
  applyLocalTunedFrequency(frequencyHz: number, forceDisplay?: boolean): void;
  armOptimisticFrequency(frequencyHz: number): void;
  escapeMapHtml(value: string): string;
  haversineKm(lat1: number, lon1: number, lat2: number, lon2: number): number;
  showHint(message: string, durationMs?: number): void;
  formatFreqForStep(frequencyHz: number, stepHz: number): string;
  refreshFreqDisplay(): void;
  setJogDivisor(divisor: number): void;
  mwDefaultsForMode(mode: string): [number, number, number, number];
  resetRdsDisplay(): void;
  positionRdsPsOverlay(): void;
  updateWfmControls(): void;
  updateSdrSquelchControlVisibility(): void;
  updateDocumentTitle(rds: unknown): void;
  activeChannelRds(): unknown;
  startRxAudio(): void;
  stopRxAudio(): void;
  setRigFrequency(frequencyHz: number): void;
  syncBandwidthInput(bandwidthHz: number): void;
  scheduleSpectrumDraw(): void;
  /** Repaints the mode buttons from #mode after writing to it. */
  syncModePicker(): void;
  onDecoderRegistryReady(callback: () => void): void;
}

interface HostWindow {
  trx: { state: HostState; core: HostCore };
}

const host = window as unknown as HostWindow;

export const hostState: HostState = host.trx.state;
export const hostCore: HostCore = host.trx.core;
