<script setup lang="ts">
import { ref, onMounted, onUnmounted, watch } from 'vue'
import { generateHumanSpriteSheet, getBotColors, HUMAN_ANIMATIONS, HUMAN_MAX_FRAMES, HUMAN_FRAME_SIZE } from '../game/sprites'

const props = defineProps<{
  seed: string
  archetype?: string
  size?: number
  winRate?: number
  anim?: keyof typeof HUMAN_ANIMATIONS
}>()

const canvasRef = ref<HTMLCanvasElement>()
let img: HTMLImageElement | null = null
let frame = 0
let animHandle: ReturnType<typeof setTimeout> | null = null

function render() {
  if (!canvasRef.value || !img?.complete) return
  const ctx = canvasRef.value.getContext('2d')!
  const displaySize = props.size || 64
  canvasRef.value.width = displaySize
  canvasRef.value.height = displaySize
  ctx.clearRect(0, 0, displaySize, displaySize)
  ctx.imageSmoothingEnabled = false

  const animName = props.anim || 'idle'
  const animCfg = HUMAN_ANIMATIONS[animName]
  const f = frame % animCfg.frames
  ctx.drawImage(
    img,
    f * HUMAN_FRAME_SIZE, animCfg.row * HUMAN_FRAME_SIZE, HUMAN_FRAME_SIZE, HUMAN_FRAME_SIZE,
    0, 0, displaySize, displaySize,
  )

  frame++
  animHandle = setTimeout(() => render(), 180)
}

function loadSprite() {
  const colors = getBotColors(props.seed)
  const dataUrl = generateHumanSpriteSheet(props.seed, props.archetype || 'standard', colors.primary, colors.secondary, props.winRate ?? 0.5)
  img = new Image()
  img.onload = () => render()
  img.src = dataUrl
}

onMounted(() => loadSprite())

watch(() => [props.seed, props.archetype, props.winRate, props.anim], () => {
  if (animHandle) clearTimeout(animHandle)
  frame = 0
  loadSprite()
})

onUnmounted(() => {
  if (animHandle) clearTimeout(animHandle)
})
</script>

<template>
  <canvas
    ref="canvasRef"
    :style="{ width: `${size || 64}px`, height: `${size || 64}px`, imageRendering: 'pixelated' }"
  />
</template>
