<script lang="ts" setup>
import {getParametricEquation} from "@/utils/chart";
import * as echarts from "echarts";
import 'echarts-gl' // 3d图表库
import {waterQualitys} from "@/utils/unit.js";
import {nextTick, onMounted, onUnmounted, ref} from "vue";

defineExpose({loadChart, carousel, bindListen, markLineChange})

const chartRef = ref(null)
let chart = null
let timer = undefined
let selectedIndex = ''
let hoveredIndex = ''

async function loadChart(option, type = null) {
  if (!chart) {
    await nextTick(); // 确保DOM已经渲染完成
    chart = echarts.init(chartRef.value);
  }
  chart.setOption(option, true);
  setTimeout(() => chart.resize(), 1000)

  if (type && type === 'bindListen') {
    bindListen();
  }
}

function markLineChange(index) {
  if (chart) {
    const option = chart.getOption()
    option.series[0].markLine.data = [{xAxis: index}]
    chart.setOption(option, true);
  }
}

function reloadChart() {
  const checkAndResize = () => {
    if (chart) {
      chart.resize();
    } else {
      setTimeout(checkAndResize, 1000);
    }
  };
  checkAndResize();
}

/* 轮播 */
function carousel(timeout = 5000, yAxisChange = false) {
  const checkAndCarousel = () => {
    if (chart) {
      // 获取legend的data
      const legendData = chart.getOption().legend[0].data
      // 首次总是从0开始的
      let i = 0
      // 开始轮播
      timer = setInterval(() => {
        // 激活
        chart.dispatchAction({
          type: 'legendToggleSelect',
          name: legendData[++i % legendData.length]
        })
      }, 10000)

      if (yAxisChange) {
        chart.on('legendselectchanged', function (params) {
          let selected = undefined;
          for (let key in params.selected) {
            if (params.selected[key] === true) {
              selected = key;
              break
            }
          }

          let field = waterQualitys.find(i => i.label === selected)
          if (field) {
            chart.setOption({yAxis: {name: field.unit,}});
          }
        });
      }
    } else {
      setTimeout(checkAndCarousel, 1000);
    }
  }
  checkAndCarousel();
}

// 监听鼠标事件，实现饼图选中效果（单选），近似实现高亮（放大）效果。
function bindListen() {
  // 监听点击事件，实现选中效果（单选）
  chart.on('click', (params) => {
    const option = chart.getOption()
    // 从 option.series 中读取重新渲染扇形所需的参数，将是否选中取反。
    const isSelected = !option.series[params.seriesIndex].pieStatus.selected
    const isHovered = option.series[params.seriesIndex].pieStatus.hovered
    const k = option.series[params.seriesIndex].pieStatus.k
    const startRatio = option.series[params.seriesIndex].pieData.startRatio
    const endRatio = option.series[params.seriesIndex].pieData.endRatio
    // 如果之前选中过其他扇形，将其取消选中（对 option 更新）
    if (selectedIndex !== '' && selectedIndex !== params.seriesIndex) {
      option.series[selectedIndex].parametricEquation = getParametricEquation(
        option.series[selectedIndex].pieData.startRatio,
        option.series[selectedIndex].pieData.endRatio,
        false,
        false,
        k,
        option.series[selectedIndex].pieData.value
      )
      option.series[selectedIndex].pieStatus.selected = false
    }
    // 对当前点击的扇形，执行选中/取消选中操作（对 option 更新）
    option.series[params.seriesIndex].parametricEquation = getParametricEquation(
      startRatio,
      endRatio,
      isSelected,
      isHovered,
      k,
      option.series[params.seriesIndex].pieData.value
    )
    option.series[params.seriesIndex].pieStatus.selected = isSelected
    // 如果本次是选中操作，记录上次选中的扇形对应的系列号 seriesIndex
    selectedIndex = isSelected ? params.seriesIndex : null
    // 使用更新后的 option，渲染图表
    chart.setOption(option)
  })
  // 监听 mouseover，近似实现高亮（放大）效果
  chart.on('mouseover', (params) => {
    const option = chart.getOption()
    // 准备重新渲染扇形所需的参数
    let isSelected
    let isHovered
    let startRatio
    let endRatio
    let k
    // 如果触发 mouseover 的扇形当前已高亮，则不做操作
    if (hoveredIndex === params.seriesIndex) {
      // 否则进行高亮及必要的取消高亮操作
    } else {
      // 如果当前有高亮的扇形，取消其高亮状态（对 option 更新）
      if (hoveredIndex !== '') {
        // 从 option.series 中读取重新渲染扇形所需的参数，将是否高亮设置为 false。
        isSelected = option.series[hoveredIndex].pieStatus.selected
        isHovered = false
        startRatio = option.series[hoveredIndex].pieData.startRatio
        endRatio = option.series[hoveredIndex].pieData.endRatio
        k = option.series[hoveredIndex].pieStatus.k
        // 对当前点击的扇形，执行取消高亮操作（对 option 更新）
        option.series[
          hoveredIndex
          ].parametricEquation = getParametricEquation(
          startRatio,
          endRatio,
          isSelected,
          isHovered,
          k,
          option.series[hoveredIndex].pieData.value
        )
        option.series[hoveredIndex].pieStatus.hovered = isHovered
        // 将此前记录的上次选中的扇形对应的系列号 seriesIndex 清空
        hoveredIndex = ''
      }
      // 如果触发 mouseover 的扇形不是透明圆环，将其高亮（对 option 更新）
      if (
        params.seriesName !== 'mouseoutSeries' &&
        params.seriesName !== 'pie2d'
      ) {
        // 从 option.series 中读取重新渲染扇形所需的参数，将是否高亮设置为 true。
        isSelected =
          option.series[params.seriesIndex].pieStatus.selected
        isHovered = true
        startRatio =
          option.series[params.seriesIndex].pieData.startRatio
        endRatio = option.series[params.seriesIndex].pieData.endRatio
        k = option.series[params.seriesIndex].pieStatus.k
        // 对当前点击的扇形，执行高亮操作（对 option 更新）
        option.series[
          params.seriesIndex
          ].parametricEquation = getParametricEquation(
          startRatio,
          endRatio,
          isSelected,
          isHovered,
          k,
          option.series[params.seriesIndex].pieData.value * 1.3
        )
        option.series[
          params.seriesIndex
          ].pieStatus.hovered = isHovered
        // 记录上次高亮的扇形对应的系列号 seriesIndex
        hoveredIndex = params.seriesIndex
      }
      // 使用更新后的 option，渲染图表
      chart.setOption(option)
    }
  })
  // 修正取消高亮失败的 bug
  chart.on('globalout', () => {
    const option = chart.getOption()
    // 准备重新渲染扇形所需的参数
    let isSelected
    let isHovered
    let startRatio
    let endRatio
    let k
    if (hoveredIndex !== '') {
      // 从 option.series 中读取重新渲染扇形所需的参数，将是否高亮设置为 true。
      isSelected = option.series[hoveredIndex].pieStatus.selected
      isHovered = false
      k = option.series[hoveredIndex].pieStatus.k
      startRatio = option.series[hoveredIndex].pieData.startRatio
      endRatio = option.series[hoveredIndex].pieData.endRatio
      // 对当前点击的扇形，执行取消高亮操作（对 option 更新）
      option.series[
        hoveredIndex
        ].parametricEquation = getParametricEquation(
        startRatio,
        endRatio,
        isSelected,
        isHovered,
        k,
        option.series[hoveredIndex].pieData.value
      )
      option.series[hoveredIndex].pieStatus.hovered = isHovered
      // 将此前记录的上次选中的扇形对应的系列号 seriesIndex 清空
      hoveredIndex = ''
    }
    // 使用更新后的 option，渲染图表
    chart.setOption(option)
  })
}

onMounted(() => chartRef.value?.addEventListener("resize", reloadChart))
onUnmounted(() => {
  if (timer) {
    clearInterval(timer)
    timer = null
  }

  chartRef.value?.removeEventListener("resize", reloadChart)
  if (chart && chart.dispose) {
    chart.dispose();
  }
})
</script>

<template>
  <div ref="chartRef" class="chart-wrapper"></div>
</template>
<style lang="scss" scoped>
.chart-wrapper {
  width: 100%;
  height: 100%;
}
</style>


