// Local-only user preferences for push-to-talk. Stored in localStorage because
// the server is zero-knowledge and doesn't need to know input-device details.

const STORAGE_KEY = 'chatapp.ptt';

export interface PttSettings {
  enabled: boolean;
  // KeyboardEvent.code of the hold-to-talk key (e.g. 'Space', 'KeyV').
  key: string;
  // Human-readable label derived from the key — kept in settings so we don't
  // re-derive it on every render. Updated together with `key`.
  keyLabel: string;
}

const DEFAULTS: PttSettings = {
  enabled: false,
  key: 'Space',
  keyLabel: 'Space',
};

type Listener = (s: PttSettings) => void;
const listeners = new Set<Listener>();

let cached: PttSettings | null = null;

function read(): PttSettings {
  if (cached) return cached;
  try {
    const raw = window.localStorage.getItem(STORAGE_KEY);
    if (!raw) {
      cached = DEFAULTS;
      return cached;
    }
    const parsed = JSON.parse(raw) as Partial<PttSettings>;
    cached = {
      enabled: typeof parsed.enabled === 'boolean' ? parsed.enabled : DEFAULTS.enabled,
      key: typeof parsed.key === 'string' && parsed.key ? parsed.key : DEFAULTS.key,
      keyLabel:
        typeof parsed.keyLabel === 'string' && parsed.keyLabel
          ? parsed.keyLabel
          : DEFAULTS.keyLabel,
    };
    return cached;
  } catch {
    cached = DEFAULTS;
    return cached;
  }
}

function write(s: PttSettings): void {
  cached = s;
  try {
    window.localStorage.setItem(STORAGE_KEY, JSON.stringify(s));
  } catch {
    /* quota / private mode */
  }
  for (const l of listeners) l(s);
}

export function getPttSettings(): PttSettings {
  return read();
}

export function updatePttSettings(patch: Partial<PttSettings>): PttSettings {
  const next = { ...read(), ...patch };
  write(next);
  return next;
}

export function subscribePttSettings(listener: Listener): () => void {
  listeners.add(listener);
  return () => listeners.delete(listener);
}

// Turns a KeyboardEvent.code into a short human label (best-effort).
export function keyCodeToLabel(code: string): string {
  if (code === 'Space') return 'Space';
  if (code.startsWith('Key')) return code.slice(3);
  if (code.startsWith('Digit')) return code.slice(5);
  if (code.startsWith('Numpad')) return 'Num' + code.slice(6);
  if (code.startsWith('Arrow')) return code.slice(5) + ' Arrow';
  return code;
}
