<template>
  <div :ref="ref" class="dv-scroll-ranking-board">
    <div v-for="(item, index) in dataSource" :key="item.label" class="row-item">
      <div class="ranking-info">
        <div class="rank">No.{{ index + 1 }}</div>
        <div class="info-name">{{ item.label }}</div>
        <div class="ranking-value">{{ item.value }} {{ unit }}</div>
      </div>

      <div class="ranking-column">
        <div
          class="inside-column"
          :style="{ width: `${maxValue ? (item.value * 100) / maxValue : 100}%` }"
        >
          <div class="shine"></div>
        </div>
      </div>
    </div>
  </div>
</template>
<script setup lang="ts">
import type { CustomComponent, ResponseData } from 'open-data-v/base'
import { useData, useProp } from 'open-data-v/base'
import { computed, onMounted, onUnmounted, ref } from 'vue'

import type { RankBoard } from './type'

const props = defineProps<{
  component: CustomComponent
}>()

const dataSource = ref<
  | Array<{ label: string; value: number }>
  | ResponseData<Array<{ label: string; value: number }>>['afterData']
>([])
const dataChange = (resp: any, _?: string) => {
  if (resp.status === 'SUCCESS') {
    dataSource.value = resp.afterData
  }

  updateData(dataSource.value)
}
useData(props.component, dataChange)

const propValueChange = (propKeys: Array<string>, value: any) => {
  if (propKeys.length !== 2) return
  const [prop, key] = propKeys
  if (prop === 'bar') {
    switch (key) {
      case 'barHeight':
        barHeight.value = `${value}px`
        break
      case 'borderRadius':
        borderRadius.value = `${value}px`
        break
      case 'color1':
        color1.value = value
        break
      case 'color2':
        color2.value = value
        break
    }
  } else if (prop === 'line') {
    switch (key) {
      case 'lineHeight':
        lineHeight.value = `${value}px`
        break
      case 'borderGap':
        borderGap.value = `${value}px`
        break
      case 'lineColor':
        lineColor.value = value
        break
    }
  } else if (prop === 'text') {
    switch (key) {
      case 'fontSize':
        fontSize.value = `${value}px`
        break
      case 'labelColor':
        labelColor.value = value
        break
      case 'valueColor':
        valueColor.value = value
        break
      case 'rankColor':
        rankColor.value = value
        break
    }
  }
  if (prop === 'data' && key === 'unit') unit.value = value
}

const { propValue } = useProp<RankBoard>(props.component, propValueChange)

const unit = ref<string>(propValue.data.unit)
const barHeight = ref<string>(`${propValue.bar.barHeight}px`)

const fontSize = ref<string>(`${propValue.text.fontSize}px`)
const labelColor = ref<string>(propValue.text.labelColor || '#fff')
const valueColor = ref<string>(propValue.text.valueColor || '#fff')
const rankColor = ref<string>(propValue.text.rankColor || '#fff')
const color1 = ref<string>(propValue.bar.color1 || '#3DE7C9')
const color2 = ref<string>(propValue.bar.color2 || '#00BAFF')
const borderRadius = ref<string>(`${propValue.bar.borderRadius}px`)
const lineHeight = ref<string>(`${propValue.line.lineHeight}px`)
const borderGap = ref<string>(`${propValue.line.borderGap}px`)
const lineColor = ref<string>(propValue.line.lineColor || '#3DE7C9')
const linearGradient = computed<string>(
  () => `linear-gradient(to right, ${color1.value}, ${color2.value})`
)

const maxValue = computed<number>(() => {
  if (propValue.data.maxValue) {
    return propValue.data.maxValue
  } else {
    return Math.max(...dataSource.value.map((el) => el.value))
  }
})

const updateData = (results: Array<{ label: string; value: number }>) => {
  results.sort((a, b) => b.value - a.value)
  dataSource.value = results
}
onMounted(async () => {})

onUnmounted(() => {})
</script>
<style lang="less" scoped>
.dv-scroll-ranking-board {
  width: 100%;
  height: 100%;
  overflow: hidden;
  .row-item {
    transition: all 0.3s;
    display: flex;
    flex-direction: column;
    justify-content: center;
    overflow: hidden;
  }
  .ranking-info {
    display: flex;
    width: 100%;
    font-size: v-bind(fontSize);
    .rank {
      color: v-bind(rankColor);
      margin-right: 2px;
    }
    .info-name {
      flex: 1;
      color: v-bind(labelColor);
    }
    .ranking-value {
      color: v-bind(valueColor);
    }
  }
  .ranking-column {
    border-bottom: v-bind(lineHeight) solid v-bind(lineColor);
    margin-top: 5px;
    .inside-column {
      position: relative;
      height: v-bind(barHeight);
      background-image: v-bind(linearGradient);
      margin-bottom: v-bind(borderGap);
      border-radius: v-bind(borderRadius);
      overflow: hidden;
    }
    .shine {
      position: absolute;
      left: 0;
      top: 2px;
      height: v-bind(barHeight);
      width: 50px;
      transform: translateX(-100%);
      background: radial-gradient(v-bind(color1) 5%, transparent 80%);
      animation: shine 3s ease-in-out infinite alternate;
    }
  }
}
@keyframes shine {
  80% {
    left: 0;
    transform: translateX(-100%);
  }
  100% {
    left: 100%;
    transform: translateX(0%);
  }
}
</style>
