<template>
  <div
    :class="[
      cn.b(),
      cn.is('timer', !indeterminate && remainingTime > 0),
      cn.is('indeterminate', indeterminate),
    ]"
  >
    <svg :class="[cn.e('circle-wrapper')]">
      <circle
        :class="[cn.e('circle')]"
        cx="50%"
        cy="50%"
        r="45%"
      />
      <circle
        :class="[cn.e('inner')]"
        cx="50%"
        cy="50%"
        r="45%"
      />
    </svg>
    <div
      v-if="showSeconds && remainingTime > 0"
      :class="[cn.e('remaining-time')]"
    >
      {{ remainingTime }}
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import useClassname from '../../composables/use-classname.js'

export interface Props {
  delay?: number
  showSeconds?: boolean
}

defineOptions({
  name: 'UiSpinner',
})

const props = withDefaults(defineProps<Props>(), {
  delay: 0,
  showSeconds: false,
})

const emit = defineEmits<{
  done: []
}>()

const cn = useClassname('ui-spinner')

const remainingTime = ref(0)

const indeterminate = computed(() => props.delay === 0)

function countdown() {
  let startTimestamp: number, elapsedTime: number

  const step = (timestamp: number) => {
    startTimestamp = startTimestamp || timestamp
    elapsedTime = timestamp - startTimestamp

    remainingTime.value = Math.ceil(props.delay - elapsedTime / 1000)

    if (elapsedTime < props.delay * 1000)
      window.requestAnimationFrame(step)
    else
      emit('done')
  }

  window.requestAnimationFrame(step)
}

onMounted(() => {
  if (props.delay > 0)
    countdown()
})
</script>

<style lang="scss">
@use 'styles';
</style>
