// Styles
import './VVideoVolume.sass'

// Components
import { VIcon } from '@/components/VIcon/VIcon'
import { VIconBtn } from '@/components/VIconBtn/VIconBtn'
import { VMenu } from '@/components/VMenu/VMenu'
import { VSlider } from '@/components/VSlider/VSlider'

// Composables
import { makeComponentProps } from '@/composables/component'
import { useLocale } from '@/composables/locale'
import { useProxiedModel } from '@/composables/proxiedModel'

// Directives
import vTooltip from '@/directives/tooltip'

// Utilities
import { ref, shallowRef, toRef } from 'vue'
import { EventProp, genericComponent, propsFactory, useRender } from '@/util'

// Types
import type { PropType } from 'vue'

export const makeVVideoVolumeProps = propsFactory({
  inline: Boolean,
  label: String,
  direction: {
    type: String as PropType<'horizontal' | 'vertical'>,
    default: 'vertical',
  },
  modelValue: {
    type: Number,
    default: 0,
  },
  menuProps: Object as PropType<VMenu['$props']>,
  sliderProps: Object as PropType<Pick<VSlider['$props'], 'color' | 'disabled' | 'thumbSize' | 'trackColor' | 'maxWidth' | 'width'>>,
  onClick: EventProp<[MouseEvent | KeyboardEvent]>(),

  ...makeComponentProps(),
}, 'VVideoVolume')

export const VVideoVolume = genericComponent()({
  name: 'VVideoVolume',

  directives: { vTooltip: vTooltip as any },

  props: makeVVideoVolumeProps(),

  emits: {
    'update:modelValue': (val: number) => true,
  },

  setup (props, { attrs }) {
    const { t } = useLocale()
    const volume = useProxiedModel(props, 'modelValue')

    const volumeIcon = toRef(() => volume.value > 70 ? '$volumeHigh'
      : volume.value > 40 ? '$volumeMedium'
      : volume.value > 10 ? '$volumeLow'
      : '$volumeOff')

    const containerRef = ref<HTMLElement>()
    const menu = shallowRef(false)

    useRender(() => {
      const sliderDefaults = {
        hideDetails: true,
        step: 5,
        thumbSize: 16,
      }

      return (
        <div
          class={[
            'v-video-volume',
            { 'v-video-volume--inline': props.inline },
            props.class,
          ]}
          style={ props.style }
          ref={ containerRef }
        >
            <VIconBtn
              icon={ volumeIcon.value }
              aria-label={ props.label }
              v-tooltip={[{
                text: props.label,
                location: 'top',
                disabled: menu.value,
              }]}
              onClick={ props.onClick as any }
              { ...attrs }
            >
              <VIcon />
              { !props.inline && (
                <VMenu
                  v-model={ menu.value }
                  activator="parent"
                  attach={ containerRef.value }
                  closeOnContentClick={ false }
                  location={ props.menuProps?.location ?? 'top center' }
                  offset="8"
                >
                  <div
                    class={[
                      'v-video-volume__menu',
                      `v-video-volume__menu--${props.direction}`,
                    ]}
                  >
                    <VSlider
                      direction={ props.direction }
                      aria-label={ t('$vuetify.video.volume') }
                      modelValue={ volume.value }
                      onUpdate:modelValue={ v => volume.value = v }
                      { ...sliderDefaults }
                      { ...props.sliderProps }
                    />
                  </div>
                </VMenu>
              )}
            </VIconBtn>

            { props.inline && (
              <VSlider
                class="v-video-volume-inline__slider"
                minWidth="50"
                aria-label={ t('$vuetify.video.volume') }
                modelValue={ volume.value }
                onUpdate:modelValue={ v => volume.value = v }
                onKeydown={ (e: KeyboardEvent) => { e.stopPropagation() } }
                { ...sliderDefaults }
                { ...props.sliderProps }
              />
            )}
        </div>
      )
    })
  },
})

export type VVideoVolume = InstanceType<typeof VVideoVolume>
