<template>
  <AudioPlayer
    v-if="isHostVisible"
    controlled
    :visible="visible"
    :audio="currentAudio"
    :playing="playing"
    :loading="loading"
    :playback-error="error"
    :current-time="currentTime"
    :duration-value="duration"
    :closable="closable"
    :expandable="expandable"
    :avoid-bottom-nav="avoidBottomNav"
    :mode="currentDisplayMode"
    @toggle="handleToggle"
    @collapse="handleCollapse"
    @stop="handleStop"
    @close="player.close"
    @seek="player.seekToPercent"
    @expand="handleExpand"
    @update:visible="handleVisibleChange"
  />
</template>

<script setup lang="ts">
import { computed, onMounted, onUnmounted, watch } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import AudioPlayer, {
  type AudioDisplayMode
} from '@/components/audio/AudioPlayer.vue'
import { useGlobalAudioPlayer } from '@/composables/useGlobalAudioPlayer'

const props = withDefaults(defineProps<{
  avoidBottomNav?: boolean
  displayMode?: AudioDisplayMode
  closable?: boolean
  expandable?: boolean
}>(), {
  avoidBottomNav: true,
  displayMode: 'mini',
  closable: true,
  expandable: true
})

const player = useGlobalAudioPlayer()
const {
  currentAudio,
  currentSource,
  visible,
  playing,
  loading,
  error,
  currentTime,
  duration,
  displayMode: currentDisplayMode,
  activeHostId,
  hasAudio
} = player
const hostId = player.registerHost()
const isHostVisible = computed(() => (
  visible.value
  && hasAudio.value
  && activeHostId.value === hostId
))

const handleToggle = () => {
  if (playing.value) {
    player.pause()
    return
  }

  void player.resume()
}

const applyHostDisplayMode = () => {
  if (!hasAudio.value) {
    return
  }

  if (currentDisplayMode.value !== props.displayMode) {
    player.setDisplayMode(props.displayMode)
  }
}

const isCurrentH5Route = (route: string) => {
  if (typeof window === 'undefined') return false

  return window.location.hash.replace(/^#/, '') === route
}

const handleStop = () => {
  player.stop()
}

const handleCollapse = () => {
  player.collapse(props.displayMode === 'floating' ? 'floating' : 'mini')
}

const handleVisibleChange = (visible: boolean) => {
  if (!visible && hasAudio.value) {
    player.collapse(props.displayMode === 'floating' ? 'floating' : 'mini')
  }
}

const handleExpand = () => {
  if (!props.expandable) return

  if (currentDisplayMode.value === 'floating') {
    player.setDisplayMode('mini')
    return
  }

  player.setDisplayMode('expanded')

  const route = currentSource.value?.detailRoute
  if (!route) {
    return
  }

  if (isCurrentH5Route(route)) {
    return
  }

  uni.navigateTo({
    url: route
  })
}

onMounted(() => {
  player.activateHost(hostId)
  applyHostDisplayMode()
})

onShow(() => {
  player.activateHost(hostId)
  applyHostDisplayMode()
})

onUnmounted(() => {
  player.unregisterHost(hostId)
})

watch(
  () => props.displayMode,
  () => {
    applyHostDisplayMode()
  }
)

watch(hasAudio, () => {
  applyHostDisplayMode()
})
</script>
