<template>
  <div
    :style="{
      ...styleMap?.mainStyle
    }"
    class="relative w-full h-full box-border overflow-hidden"
  >
    <ImageBg
      v-if="styleMap?.mainStyle?.imageSrc"
      :src="styleMap.mainStyle.imageSrc"
      :imageStyle="styleMap.mainStyle.imageStyle"
    />

    <svg
      :viewBox="`0 0 ${width} ${height}`"
      preserveAspectRatio="xMidYMid meet"
      class="w-full h-full block"
      xmlns="http://www.w3.org/2000/svg"
      :style="svgStyle"
    >
      <defs>
        <!-- 背景条图片 pattern：保持图像原始尺寸，居中显示 -->
        <pattern
          v-if="styleMap?.mainStyle?.curve?.imageSrc"
          :id="`${spinnerId}-bg-pattern`"
          patternUnits="userSpaceOnUse"
          :width="width"
          :height="height"
          x="0"
          y="0"
        >
          <image :href="styleMap.mainStyle.curve.imageSrc" transform="translate(-50%, -50%)" />
        </pattern>

        <!-- 指示条图片 pattern：保持图像原始尺寸，居中显示 -->
        <pattern
          v-if="styleMap?.indicatorStyle?.curve?.imageSrc"
          :id="`${spinnerId}-indicator-pattern`"
          patternUnits="userSpaceOnUse"
          :width="width"
          :height="height"
          x="0"
          y="0"
        >
          <image
            :href="styleMap.indicatorStyle.curve.imageSrc"
            transform="translate(-50%, -50%)"
          />
        </pattern>
      </defs>

      <!-- 背景环：0 度从顶部开始，顺时针绘制整圆 -->
      <path
        :d="bgPath"
        fill="none"
        :stroke="
          styleMap?.mainStyle?.curve?.imageSrc
            ? `url(#${spinnerId}-bg-pattern)`
            : styleMap?.mainStyle?.curve?.color || '#eeeeee'
        "
        :stroke-width="styleMap?.mainStyle?.curve?.width ?? 1"
        :stroke-linecap="styleMap?.mainStyle?.curve?.radius ? 'round' : 'butt'"
        :opacity="styleMap?.mainStyle?.curve?.opacity"
      />

      <!-- 指示环：从 0 度顶部开始，按顺时针方向延伸 length 度 -->
      <path
        v-if="indicatorPath"
        :d="indicatorPath"
        fill="none"
        :stroke="
          styleMap?.indicatorStyle?.curve?.imageSrc
            ? `url(#${spinnerId}-indicator-pattern)`
            : styleMap?.indicatorStyle?.curve?.color || '#2092f5'
        "
        :stroke-width="styleMap?.indicatorStyle?.curve?.width ??
          styleMap?.mainStyle?.curve?.width ??
          1"
        :stroke-linecap="styleMap?.indicatorStyle?.curve?.radius ? 'round' : 'butt'"
        :opacity="styleMap?.indicatorStyle?.curve?.opacity"
      />
    </svg>
  </div>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue'
import { useWidgetStyle } from '../hooks/useWidgetStyle'
import ImageBg from '../ImageBg.vue'

const spinnerId = ref('spinner-' + Math.random().toString(36).slice(2))

const props = defineProps<{
  width: number
  height: number
  styles: any
  state?: string
  part?: string
  length: number
  time: number
}>()

const styleMap = useWidgetStyle({
  widget: 'lv_spinner',
  props
})

const cx = computed(() => {
  const min = Math.min(props.width, props.height)
  return min / 2
})

/** 弧线半径：与曲线宽度一致，留出边距避免贴边 */
const trackRadius = computed(() => {
  const min = Math.min(props.width, props.height)
  const curveWidth = styleMap.value?.mainStyle?.curve?.width ?? 12
  return Math.max(4, min / 2 - curveWidth / 2)
})

/**
 * 极坐标转直角坐标
 * 这里定义：0 度在顶部（12 点钟），角度按顺时针增加
 */
function polarToCartesian(
  centerX: number,
  centerY: number,
  radius: number,
  angleInDegrees: number
) {
  const radians = ((angleInDegrees - 90) * Math.PI) / 180.0
  return {
    x: centerX + radius * Math.cos(radians),
    y: centerY + radius * Math.sin(radians)
  }
}

/**
 * 生成 SVG 弧线路径指令
 * 始终从 startAngle 顺时针画到 endAngle
 */
function describeArc(x: number, y: number, radius: number, startAngle: number, endAngle: number) {
  // 归一化到 [0, 360)
  const s = ((startAngle % 360) + 360) % 360
  const e = ((endAngle % 360) + 360) % 360

  // 顺时针跨度
  let span = (e - s + 360) % 360
  // 0/360 视作整圆，避免 SVG 报错
  if (span === 0) span = 359.999

  const start = polarToCartesian(x, y, radius, s)
  const end = polarToCartesian(x, y, radius, s + span)
  const largeArcFlag = span > 180 ? '1' : '0'
  const sweepFlag = '1' // 顺时针

  return [
    'M',
    start.x,
    start.y,
    'A',
    radius,
    radius,
    0,
    largeArcFlag,
    sweepFlag,
    end.x,
    end.y
  ].join(' ')
}

// 背景整圆：0~360 度，0 在顶部
const bgPath = computed(() => {
  const r = trackRadius.value
  return describeArc(cx.value, cx.value, r, 0, 360)
})

// 指示弧：从 0 度开始，顺时针 length 度
const indicatorPath = computed(() => {
  const r = trackRadius.value
  const len = Math.max(0, Math.min(360, props.length ?? 0))
  if (!len) return ''
  return describeArc(cx.value, cx.value, r, 0, len)
})

// 旋转动画：使用 time 作为一圈的时长（ms）
const svgStyle = computed(() => {
  if (!props.time || props.time <= 0) return {}
  return {
    animation: `lv-spinner-rotate ${props.time}ms linear infinite`,
    transformOrigin: '50% 50%'
  }
})
</script>

<style scoped>
@keyframes lv-spinner-rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
</style>

