<template>
  <div
    class="overflow-hidden rounded-xl transition-[background-color]"
    :class="{
      'hover:bg-surface-800 cursor-pointer': !isMe,
      'bg-surface-800': expanded,
    }"
  >
    <div class="p-3" @click="toggleExpand">
      <div class="flex items-center gap-3">
        <PrimeAvatar
          size="small"
          class="shrink-0"
          :class="{
            'outline-1 outline-primary outline-offset-2': speaking,
          }"
        >
          <template #icon>
            <User :size="20" />
          </template>
        </PrimeAvatar>

        <p class="flex-1 text-sm leading-5 font-medium text-color truncate w-0">
          {{ client.displayName || client.username }}
        </p>

        <Component :is="expanded ? ChevronUp : ChevronDown" v-if="!isMe" :size="20" class="text-muted-color" />
      </div>

      <div v-if="hasBadges" class="flex justify-end align-center gap-1 mt-2">
        <PrimeBadge v-if="!!shareConsumer" v-tooltip.top="'Watch'" severity="success" value="Streaming" size="small" @click.stop="watchStream" />

        <PrimeBadge v-if="premuted" severity="danger" value="Muted" size="small" />
        <PrimeBadge v-else-if="client.outputMuted" severity="info" value="No sound" size="small" />
        <PrimeBadge v-else-if="inputMuted" severity="info" value="Muted" size="small" />

        <PrimeBadge v-if="isMe" severity="secondary" value="You" size="small" class="shrink-0" />
      </div>
    </div>

    <CollapseTransition v-if="!isMe">
      <div v-if="expanded">
        <div class="px-3 pb-3">
          <div class="flex justify-between text-sm mb-3">
            <span>Volume</span>
            <span>{{ volume }}</span>
          </div>
          <PrimeSlider v-model="volume" :min="0" :max="1000" :step="volume < 200 ? 5 : 25" />

          <div class="mt-3 flex gap-1 justify-end">
            <PrimeButton size="small" variant="text" @click="premuted = !premuted">
              {{ premuted ? 'Unmute' : 'Mute' }}
            </PrimeButton>
          </div>
        </div>
      </div>
    </CollapseTransition>
  </div>
</template>

<script setup lang="ts">
import type { ChadClient } from '#shared/types'
import { useLocalStorage } from '@vueuse/core'
import { ChevronDown, ChevronUp, User } from 'lucide-vue-next'
import CollapseTransition from '~/components/CollapseTransition.vue'

const props = defineProps<{
  client: ChadClient
}>()

const { outputMuted } = useApp()
const { consumers: allConsumers, micProducer, speakingClients } = useMediasoup()
const { me } = useClients()
const { show } = useFullscreenVideo()

const expanded = ref(false)

const volume = useLocalStorage<number>(computed(() => `CLIENT_VOLUME_${props.client.userId}`), 100, { writeDefaults: false })
const premuted = useLocalStorage<boolean>(computed(() => `CLIENT_PREMUTED_${props.client.userId}`), false, { writeDefaults: false })

const isMe = computed(() => {
  return me.value && props.client.userId === me.value.userId
})

const consumers = computed(() => {
  return allConsumers.value.values().filter(consumer => consumer.appData.socketId === props.client.socketId).toArray()
})

const audioConsumer = computed(() => {
  return consumers.value.find(consumer => consumer.track.kind === 'audio')
})

const videoConsumers = computed(() => {
  return consumers.value.filter(consumer => consumer.track.kind === 'video')
})

const shareConsumer = computed(() => {
  return videoConsumers.value.find(consumer => consumer.appData.source === 'share')
})

const audioTrack = computed(() => {
  return audioConsumer.value?.track
})

const speaking = computed(() => {
  return speakingClients.value.find(speaker => speaker.clientId === props.client.socketId)
})

const audioConsumerPaused = ref(false)

const inputMuted = computed(() => {
  if (isMe.value)
    return micProducer.value?.paused ?? false

  return premuted.value || audioConsumerPaused.value
})

const hasBadges = computed(() => {
  return !!shareConsumer.value
    || premuted.value
    || inputMuted.value
    || props.client.outputMuted
    || isMe.value
})

watch(allConsumers, () => {
  audioConsumerPaused.value = audioConsumer.value?.paused ?? false
})

const { setGain } = useAudioContext(audioTrack)

watchEffect(() => {
  setGain((outputMuted.value || premuted.value) ? 0 : (volume.value * 0.01))
})

function toggleExpand() {
  if (isMe.value)
    return

  expanded.value = !expanded.value
}

function watchStream() {
  if (!shareConsumer.value)
    return

  show(new MediaStream([shareConsumer.value.track]))
}
</script>
