import {Room as LiveKitRoom} from "livekit-client"
import {derived, writable} from "svelte/store"
import {type Room} from "@app/core/state"

export type VoiceSession = {
  url: string
  h: string
  room: LiveKitRoom
  muted: boolean
  cameraOn: boolean
  screenShareOn: boolean
}

export type Pubkey = string

export type VoiceParticipant = {pubkey?: Pubkey; identity: string}

export enum VoiceState {
  Joining = "joining",
  Connected = "connected",
  Disconnected = "disconnected",
}

export const currentVoiceSession = writable<VoiceSession | undefined>(undefined)

export const voiceState = writable<VoiceState>(VoiceState.Disconnected)

export const currentVoiceRoom = writable<Room | undefined>(undefined)

export const participantPubkeyMap = writable<Map<string, Pubkey>>(new Map())

export const pubkeyFromLiveKitIdentity = (identity: string): string | undefined =>
  /^[a-f0-9]{64}$/.test(identity.slice(0, 64)) ? identity.slice(0, 64) : undefined

export const participantFromLiveKitIdentity = (identity: string): VoiceParticipant => {
  const pk = pubkeyFromLiveKitIdentity(identity)
  return pk ? {pubkey: pk, identity} : {identity}
}

export const participantKey = (p: VoiceParticipant) => p.pubkey ?? p.identity

export const speakingParticipants = writable<VoiceParticipant[]>([])

export const isParticipantSpeaking = derived(
  speakingParticipants,
  $participants => (p: VoiceParticipant) =>
    $participants.some(sp => participantKey(sp) === participantKey(p)),
)

export const isLocalSpeaking = derived(
  [currentVoiceSession, speakingParticipants],
  ([$session, $speaking]) => {
    if (!$session?.room) return false
    const local = participantFromLiveKitIdentity($session.room.localParticipant.identity)
    return $speaking.some(sp => participantKey(sp) === participantKey(local))
  },
)
