// The shared app-event dispatcher. The host exposes ONE registerAppEvent slot per JS world
// (docs/app-lifecycle-plan.md), so every SDK consumer (the `app` global's pause/resume/url, the
// `device` global's online/offline) subscribes here and this module registers with the host once,
// lazily on the first subscription — no top-level side effect, tree-shaking drops it when unused.

type AppEventCallback = (data?: string) => void

const listeners: Record<string, AppEventCallback[]> = {}
let registered = false

const dispatch = (event: string, data?: string): void => {
  const arr = listeners[event]
  if (arr) for (const cb of arr.slice()) cb(data)
}

export const appEventsOn = (event: string, cb: AppEventCallback): void => {
  ;(listeners[event] ??= []).push(cb)
  if (!registered) {
    registered = true
    _creatorUtils.registerAppEvent?.(dispatch)
  }
}

export const appEventsOff = (event: string, cb: AppEventCallback): void => {
  const arr = listeners[event]
  if (!arr) return
  const i = arr.indexOf(cb)
  if (i >= 0) arr.splice(i, 1)
}

// The keyboard channel is a separate host slot (registerKeyboardEvent) — the registerAppEvent
// string channel can't carry the (height, duration) number pair. Same lazy single-slot pattern.

type KeyboardCallback = (height: number, duration: number) => void

const keyboardListeners: KeyboardCallback[] = []
let keyboardRegistered = false

const dispatchKeyboard = (height: number, duration: number): void => {
  for (const cb of keyboardListeners.slice()) cb(height, duration)
}

export const keyboardEventsOn = (cb: KeyboardCallback): void => {
  keyboardListeners.push(cb)
  if (!keyboardRegistered) {
    keyboardRegistered = true
    _creatorUtils.registerKeyboardEvent?.(dispatchKeyboard)
  }
}

export const keyboardEventsOff = (cb: KeyboardCallback): void => {
  const i = keyboardListeners.indexOf(cb)
  if (i >= 0) keyboardListeners.splice(i, 1)
}
