<template>
  <div :style="styleMap?.mainStyle" class="w-full h-full overflow-hidden relative box-border">
    <div class="lottie-preview">
      <DotLottieVue
        v-if="animationData"
        :key="playerKey"
        class="lottie-preview__player"
        autoplay
        loop
        :data="animationData"
        :autoResizeCanvas="true"
        :renderConfig="renderConfig"
        :layout="layout"
      />
      <div v-else class="lottie-preview__empty">
        <img :src="icon" />
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { DotLottieVue } from '@lottiefiles/dotlottie-vue'
import { useProjectStore } from '@/store/modules/project'
import { useWidgetStyle } from '../hooks/useWidgetStyle'
import { getFileByPath } from '@/utils'
import icon from '../assets/icon/icon_39lottie.svg'

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

const projectStore = useProjectStore()
const animationData = ref('')
const layout = {
  fit: 'fill' as const,
  align: [0.5, 0.5] as [number, number]
}

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

const lottieMeta = ref<{
  width?: number
  height?: number
  frameRate?: number
  frames?: number
  valid: boolean
}>({
  valid: false
})

const resource = computed(() => {
  return projectStore.project?.resources.others.find((item) => item.id === props.lottie)
})

const playerKey = computed(() => `${props.lottie}-${props.width}-${props.height}`)

const renderConfig = computed(() => {
  const dpr =
    typeof window !== 'undefined' ? Math.min(4, Math.max(window.devicePixelRatio || 1, 2)) : 2

  return {
    devicePixelRatio: dpr
  }
})

watch(
  () => [props.lottie, projectStore.projectPath],
  async () => {
    lottieMeta.value = { valid: false }
    animationData.value = ''

    if (!props.lottie || !resource.value?.path || !projectStore.projectPath) {
      return
    }

    try {
      const content = await getFileByPath(projectStore.projectPath + resource.value.path, 'utf-8')
      if (!content) return

      animationData.value = content
      const json = JSON.parse(content)
      const frameStart = Number(json?.ip)
      const frameEnd = Number(json?.op)
      lottieMeta.value = {
        width: Number(json?.w) || undefined,
        height: Number(json?.h) || undefined,
        frameRate: Number(json?.fr) || undefined,
        frames:
          Number.isFinite(frameStart) && Number.isFinite(frameEnd)
            ? Math.max(0, Math.round(frameEnd - frameStart))
            : undefined,
        valid: true
      }
    } catch {
      lottieMeta.value = { valid: false }
    }
  },
  {
    immediate: true
  }
)
</script>

<style scoped>
.lottie-preview {
  width: 100%;
  height: 100%;
}

.lottie-preview__player,
.lottie-preview__empty {
  width: 100%;
  height: 100%;
}

.lottie-preview__player {
  display: block;
}

.lottie-preview__empty {
  display: grid;
  place-items: center;
}
</style>
