<template>
  <span>{{ displayValue }}</span>
</template>

<script setup lang="ts">
import { ref, watch, onMounted } from 'vue'

interface Props {
  value: number
  duration?: number
  format?: (value: number) => string
  delay?: number
}

const props = withDefaults(defineProps<Props>(), {
  duration: 1000,
  format: (value: number) => value.toLocaleString(),
  delay: 0
})

const displayValue = ref(props.format(0))
const startTimestamp = ref<number | null>(null)
const startValue = ref(0)

const animate = (timestamp: number) => {
  if (!startTimestamp.value) {
    startTimestamp.value = timestamp
  }
  
  const progress = Math.min((timestamp - startTimestamp.value) / props.duration, 1)
  
  // Easing function for smooth animation
  const easeOutQuart = (t: number) => 1 - Math.pow(1 - t, 4)
  const easedProgress = easeOutQuart(progress)
  
  const currentValue = startValue.value + (props.value - startValue.value) * easedProgress
  displayValue.value = props.format(currentValue)
  
  if (progress < 1) {
    requestAnimationFrame(animate)
  }
}

const startAnimation = () => {
  startTimestamp.value = null
  
  if (props.delay > 0) {
    setTimeout(() => {
      requestAnimationFrame(animate)
    }, props.delay)
  } else {
    requestAnimationFrame(animate)
  }
}

watch(() => props.value, (newValue, oldValue) => {
  startValue.value = oldValue || 0
  startAnimation()
})

onMounted(() => {
  startAnimation()
})
</script>