<script setup lang="ts">
import VolumeDown from '@material-design-icons/svg/outlined/volume_down.svg'
import VolumeMute from '@material-design-icons/svg/outlined/volume_mute.svg'
import VolumeOff from '@material-design-icons/svg/outlined/volume_off.svg'
import VolumeUp from '@material-design-icons/svg/outlined/volume_up.svg'
import { computed, useId } from 'vue'
import Slider from '@/components/library/Slider.vue'
import classes from './ToolBar.module.css'

const {
  defaultVolume = 1,
  enableBoost = true,
} = defineProps<{
  defaultVolume?: number
  // Boost increases volume range from 0..1 up to 0..1.5
  enableBoost?: boolean
}>()

/** Muted flag. When muted, volume slider shows zero value, but remains interactive. */
const muted = defineModel<boolean>('muted', { required: true })

/** Volume in range 0..1 or 0..1.5 if boost is enabled. */
const volume = defineModel<number>('volume', { required: true })

const mutedId = useId()
const mutedTitle = computed(() => muted.value ? 'Unmute' : 'Mute')

function toggleMuted() {
  muted.value = !muted.value
}

const volumeMax = computed(() => enableBoost ? 1.5 : 1.0)
const sliderSteps = computed(() => enableBoost ? 24 : 16)

function toSteps(volume: number): number {
  return volume / volumeMax.value * sliderSteps.value
}

function fromSteps(steps: number): number {
  return steps / sliderSteps.value * volumeMax.value
}

const volumeDisplay = computed<number>({
  get() {
    // displays zero volume when muted, despite actual unmuted volume is remembered
    return muted.value ? 0 : toSteps(volume.value)
  },
  set(value: number) {
    volume.value = fromSteps(value)
  },
})

function reset() {
  volume.value = defaultVolume
}

const defaultValue = computed(() => toSteps(defaultVolume))
</script>

<template>
  <div class="tw:flex tw:flex-row tw:gap-2 tw:items-center">
    <input
      :id="mutedId"
      type="checkbox"
      class="tw:hidden"
      :title="mutedTitle"
      @click="toggleMuted"
    >
    <label
      :for="mutedId"
      :class="[classes.toolbarControl, classes.toolButton]"
      :title="mutedTitle"
      tabindex="0"
    >
      <VolumeOff v-if="muted" class="tw:text-[#e64b3d]" />
      <!-- transforms are needed because icons are centered rather than aligned with each other -->
      <VolumeMute v-else-if="volume < 0.33" style="transform: translateX(-8px);" />
      <VolumeDown v-else-if="volume < 0.66" style="transform: translateX(-4px);" />
      <VolumeUp v-else :class="{ 'tw:text-[#e8ba3d]': volume > 1.01 }" />
    </label>
    <Slider
      v-model.number="volumeDisplay"
      :min="0"
      :max="sliderSteps"
      :step="1"
      :reset="reset"
      :default-value
      title="Volume"
    />
  </div>
</template>

<style scoped></style>
