<!-- 

// 基础用法
    <VtkCount :start="0" :end="12345" :duration="3000" suffix="次" />
    
//带前缀和分隔符
    <VtkCount 
      :start="0" 
      :end="999999" 
      :duration="2000" 
      prefix="¥" 
      suffix="元" 
      :separator="true" 
    />
    
//手动控制
    <VtkCount 
      ref="countRef" 
      :start="0" 
      :end="100" 
      :autoplay="false" 
      @complete="onComplete"
    />
    <v-btn @click="startCount">开始计数</v-btn>
  -->

<template>
  <div class="vtk-count" :class="containerClass">
    <div class="count-display" :style="{ color: color }">
      <!-- 前缀 -->
      <span v-if="prefix" class="prefix">{{ prefix }}</span>
      
      <!-- 数字容器 -->
      <div class="digits-container">
        <div 
          v-for="(digitChar, index) in maxDigitString" 
          :key="`digit-${index}-${digitKey}`"
          class="digit-wrapper"
          :class="{ 'digit-separator': isNaN(digitChar) }"
        >
          <div 
            v-if="!isNaN(digitChar)" 
            class="digit-scroll"
          >
            <div 
              v-for="n in 10" 
              :key="n" 
              class="digit-item"
              :style="getDigitStyle(getCurrentDigit(index), n-1)"
            >
              {{ n-1 }}
            </div>
          </div>
          <div v-else class="separator">{{ digitChar }}</div>
        </div>
      </div>
      
      <!-- 后缀 -->
      <span v-if="suffix" class="suffix">{{ suffix }}</span>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, watch, nextTick } from 'vue'

// 定义组件名称
defineOptions({
  name: "VtkCount",
  inheritAttrs: false,
});

// 定义 props
const props = defineProps({
  // 初始值
  start: {
    type: Number,
    default: 0
  },
  // 目标值
  end: {
    type: Number,
    default: 0
  },
  // 动画持续时间（毫秒）
  duration: {
    type: Number,
    default: 2000
  },
  // 是否自动开始动画
  autoplay: {
    type: Boolean,
    default: true
  },
  // 数字前缀
  prefix: {
    type: String,
    default: ''
  },
  // 数字后缀
  suffix: {
    type: String,
    default: ''
  },
  // 容器自定义类名
  containerClass: {
    type: String,
    default: ''
  },
  // 是否使用分隔符（千分位）
  separator: {
    type: Boolean,
    default: false
  },
  // 小数位数
  decimals: {
    type: Number,
    default: 0
  },
  // 文字颜色
  color: {
    type: String,
    default: '#1976d2'
  }
})

// 定义 emits
const emit = defineEmits(['complete'])

// 当前显示的数值
const currentNumber = ref(props.start)

// 当前每个位置的数字值
const currentDigits = ref([])

// 用于强制重新渲染的key
const digitKey = ref(0)

// 是否正在动画中
const isAnimating = ref(false)

// 格式化数字（处理小数和分隔符）
const formatNumber = (num) => {
  let result = num.toFixed(props.decimals)
  if (props.separator && props.decimals === 0) {
    result = result.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
  }
  return result
}

// 获取目标数字字符串
const targetNumberString = computed(() => {
  return formatNumber(props.end)
})

// 获取起始数字字符串
const startNumberString = computed(() => {
  return formatNumber(props.start)
})

// 获取最大位数的字符串（用于保持DOM结构稳定）
const maxDigitString = computed(() => {
  const target = targetNumberString.value
  const start = startNumberString.value
  return target.length >= start.length ? target : start
})

// 获取当前指定位置的数字
const getCurrentDigit = (index) => {
  if (index < currentDigits.value.length) {
    return currentDigits.value[index]
  }
  return '0'
}

// 初始化数字数组
const initDigitsArray = () => {
  const targetStr = targetNumberString.value
  const startStr = startNumberString.value
  
  // 初始化currentDigits数组，确保长度与maxDigitString一致
  currentDigits.value = maxDigitString.value.split('').map((char, index) => {
    if (isNaN(char)) {
      return char // 分隔符保持原样
    }
    
    // 从起始字符串对应位置获取数字
    if (index < startStr.length) {
      const startChar = startStr[index]
      return isNaN(startChar) ? '0' : startChar
    }
    return '0'
  })
}

// 获取数字样式
const getDigitStyle = (currentValue, digitValue) => {
  // 如果是分隔符，直接返回
  if (isNaN(currentValue) || isNaN(digitValue)) {
    return {
      transform: 'translateY(0)'
    }
  }
  
  const current = parseInt(currentValue) || 0
  const target = digitValue
  const offset = target - current
  
  // 处理循环滚动（9->0 或 0->9）
  let translateY
  if (offset > 5) {
    // 向下滚动（如 9->0）
    translateY = -(10 - offset) * 100
  } else if (offset < -5) {
    // 向上滚动（如 0->9）
    translateY = (10 + offset) * 100
  } else {
    translateY = -offset * 100
  }
  
  return {
    transform: `translateY(${translateY}%)`,
    transition: isAnimating.value ? 'transform 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94)' : 'none',
    color: props.color
  }
}

// 开始数字动画
const startAnimation = () => {
  if (isAnimating.value) return
  
  isAnimating.value = true
  const startTime = performance.now()
  const startValue = props.start
  const endValue = props.end
  const diff = endValue - startValue
  
  // 初始化数字数组
  initDigitsArray()
  
  const animate = (currentTime) => {
    const elapsed = currentTime - startTime
    const progress = Math.min(elapsed / props.duration, 1)
    
    // 使用缓动函数使动画更自然
    const easeOutQuart = 1 - Math.pow(1 - progress, 4)
    currentNumber.value = startValue + diff * easeOutQuart
    
    // 更新每个数字位的当前值
    updateDigitArray(currentNumber.value)
    
    if (progress < 1) {
      requestAnimationFrame(animate)
    } else {
      currentNumber.value = endValue
      // 确保最终值准确
      updateDigitArray(endValue)
      isAnimating.value = false
      emit('complete')
    }
  }
  
  requestAnimationFrame(animate)
}

// 更新数字数组
const updateDigitArray = (value) => {
  const valueStr = formatNumber(value)
  const maxStr = maxDigitString.value
  
  // 保持数组长度不变，只更新值
  for (let i = 0; i < maxStr.length; i++) {
    if (i < valueStr.length) {
      currentDigits.value[i] = valueStr[i]
    } else {
      // 超出部分保持为'0'或分隔符
      currentDigits.value[i] = isNaN(maxStr[i]) ? maxStr[i] : '0'
    }
  }
}

// 监听 end 值变化，重新开始动画
watch(() => props.end, (newVal, oldVal) => {
  if (newVal !== oldVal) {
    // 当位数可能发生变化时，更新key强制重新渲染
    const newStr = formatNumber(newVal)
    const oldStr = formatNumber(oldVal)
    if (newStr.length !== oldStr.length) {
      digitKey.value += 1
      nextTick(() => {
        startAnimation()
      })
    } else {
      startAnimation()
    }
  }
})

// 组件挂载时开始动画
onMounted(() => {
  if (props.autoplay) {
    // 检查初始值和目标值位数是否不同，如果不同则更新key
    const startStr = startNumberString.value
    const endStr = targetNumberString.value
    if (startStr.length !== endStr.length) {
      digitKey.value += 1
    }
    
    nextTick(() => {
      startAnimation()
    })
  }
})

// 提供外部调用方法
defineExpose({
  startAnimation
})
</script>

<style scoped>
.vtk-count {
  display: inline-block;
}

.count-display {
  display: flex;
  align-items: center;
  font-family: 'Roboto Mono', monospace;
  font-size: 24px;
  font-weight: bold;
}

.digits-container {
  display: flex;
  align-items: center;
}

.digit-wrapper {
  position: relative;
  width: 1em;
  height: 1em;
  overflow: hidden;
  text-align: center;
  margin: 0 1px;
}

.digit-wrapper.digit-separator {
  width: auto;
  animation: none;
}

.digit-scroll {
  position: relative;
  height: 100%;
}

.digit-item {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.separator {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  font-weight: normal;
}

.prefix, .suffix {
  font-size: 0.8em;
  align-self: flex-end;
  margin-bottom: 0.1em;
}

.prefix {
  margin-right: 4px;
}

.suffix {
  margin-left: 4px;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .count-display {
    font-size: 20px;
  }
}

@media (max-width: 480px) {
  .count-display {
    font-size: 18px;
  }
}
</style>