<template>
  <div class="device-data-chart">
    <v-chart
      class="chart"
      ref="chartRef"
      :option="chartOption"
      :autoresize="autoresize"
      :loading-options="loadingOpt"
      :loading="loading"
      @click="onChartClick"
    />
  </div>
  <LineChartDlg ref="LineChartDlgRef" @on-save="onChangeCoefficient"/>
</template>

<script setup lang="ts">
import Big from 'big.js'
import dayjs from 'dayjs'
import VChart from 'vue-echarts'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import type { EChartsOption, SeriesOption } from 'echarts/types/dist/shared.js'
import { LineChart } from 'echarts/charts'
import LineChartDlg from './line-dlg.vue'
import {
  DataZoomComponent,
  GridComponent,
  LegendComponent,
  TooltipComponent,
} from 'echarts/components'

use([
  CanvasRenderer,
  TooltipComponent,
  LineChart,
  LegendComponent,
  GridComponent,
  DataZoomComponent,
])
const ZOOM_HEIGHT = 30
const ZOOM_BOTTOM = 10
const emits = defineEmits(['on-change-coefficient'])

type Legend = {
  addr: string
  label: string
  unit?: string
  coefficient?: string | number
  operator?: string
}

const autoresize = {
  throttle: 0,
}

const LineChartDlgRef = ref()

function onChangeCoefficient(data: { id: string; coefficient: string; operator: string }) {
  emits('on-change-coefficient', data)
}

const onChartClick = (params: any) => {
  // 判断是否点到折线
  const [seriesName, id] = params?.seriesName?.split('|')
  if (params.componentType === 'series' && params.seriesType === 'line' && seriesName && id) {
    const find = props.legends.find(item => item.addr === id) as any
    if (find) {
      LineChartDlgRef.value?.open(seriesName, id, find?.coefficient, find?.operator)
    }
  }
}

const props = defineProps({
  title: String,
  smooth: Boolean, //当前是曲线图还是阶梯图
  legends: {
    type: Array as PropType<Legend[]>,
    default: () => [],
  },
  axisData: {
    type: Array as PropType<string[]>,
    default: () => [],
  },
  chartDatas: {
    type: Object as PropType<Map<string, any[]>>,
    default: () => new Map(),
  },
})

const loading = ref(true)
const loadingOpt = {
  type: 'default',
  text: '暂无数据',
  color: '#c23531',
  textColor: '#666',
  maskColor: 'rgba(0, 0, 0, 0)',
  showSpinner: false,
}

const chartRef = ref()

const chartOption = computed<EChartsOption>(() => {
  if (props.chartDatas.size === 0) {
    return {}
  }
  loading.value = false
  const tmpSeries: SeriesOption[] = []
  for (const legend of props.legends.filter(item => item.addr !== 'ts')) {
    const entry = props.chartDatas.get(legend.addr) ?? []
    const lineData: SeriesOption = {
      name: `${legend.label}|${legend.addr}`,
      type: 'line',
      id: legend.addr,
      // symbol: "none",
      connectNulls: true,
      triggerLineEvent: true,
      data: entry.map(([ts, val]) => {
        const coef = legend?.coefficient ? new Big(legend.coefficient) : new Big(1)
        const operator = legend?.operator || '*'
        let valBig = new Big(val)
        if (operator === '/') {
          valBig = valBig.div(coef)
        } else {
          valBig = valBig.times(coef)
        }
        return [ts, valBig.toNumber()]
      }),
      sampling: 'lttb',
      animation: false,
    }
    if (props.smooth) {
      lineData.smooth = true
    } else {
      lineData.step = 'middle'
    }
    tmpSeries.push(lineData)
  }
  const dataLength = tmpSeries.length * tmpSeries[0]?.data?.length || 0;
  const visibleCount = Math.min(tmpSeries.length * 1000, dataLength);

  const startPercent = dataLength === 0 ? 0 : ((dataLength - visibleCount) / dataLength) * 100;
  const endPercent = 100;
  const maxSpanPercent = dataLength === 0 ? 100 : (visibleCount / dataLength) * 100;

  const option: EChartsOption = {
    grid: {
      left: 60,
      right: 198,
      top: '5%',
      bottom: `25%`,
    },
    tooltip: {
      trigger: 'axis',
      confine: true,
      appendToBody: true,
      formatter: function (params: any) {
        // 时间格式化
        const date = new Date(params[0].value[0])
        const timeStr = dayjs(params[0].value[0]).format('YYYY-MM-DD HH:mm:ss.SSS')

        let relVal = timeStr

        for (let i = 0; i < params.length; i++) {
          const data = props.legends.find(item => item.addr === params[i].seriesId)
          const conefficients = data?.coefficient ?? undefined
          const unit = data?.unit || ''
          relVal += `<div style="display: flex; justify-content: space-between; gap: 30px;">
            <div>${params[i].marker}${params[i].seriesName}:</div>
            <div>${params[i].value[1]}${conefficients ? `【系数为${conefficients}(${operatorMap[data?.operator] ?? ''
          })】` : ''}${unit}</div>
          </div>`
        }
        return relVal
      }
    },
    legend: {
      type: 'scroll',
      orient: 'vertical',
      formatter: name => {
        const nameStr = name.split('|')[0]
        return nameStr.length > 15 ? nameStr.substring(0, 15) + '...' : nameStr
      },
      tooltip: {
        show: true,
        formatter: function (params) {
          return params.name.split('|')[0]
        },
      },
      right: 0,
      top: 20,
      itemWidth: 10,
      itemHeight: 10,
      pageIconSize: 12,
      data: props.legends.map(item => `${item.label}|${item.addr}`),
      // selected: unCheckArr.value.reduce((acc, cur) => {
      //   acc[cur] = false
      //   return acc
      // }, {} as Record<string, boolean>),
    },
    xAxis: {
      type: 'time',
      axisLine: {
        //y轴线的颜色以及宽度
        show: true,
        lineStyle: {
          width: 1,
          type: 'solid',
        },
      },
      axisLabel: {
        show: false,
      }
    },
    yAxis: {
      type: 'value',
      splitNumber: 6,
      axisLine: {
        //y轴线的颜色以及宽度
        show: true,
        lineStyle: {
          width: 1,
          type: 'solid',
        },
      },
      axisLabel: {
        margin: 12,
        fontSize: 12,
      },
      splitLine: {
        show: true,
        lineStyle: {},
      },
    },
    dataZoom: [
      {
        type: 'inside',
        xAxisIndex: 0,
        filterMode: 'filter',
        start: startPercent,
        end: endPercent,
        // maxSpan: maxSpanPercent,
      },
      {
        type: 'slider',
        xAxisIndex: 0,
        start: startPercent,
        end: endPercent,
        height: ZOOM_HEIGHT,
        bottom: '20%',
        borderColor: '#88abf5',
        dataBackground: { lineStyle: { color: '#d2dbee' } },
        selectedDataBackground: { lineStyle: { color: '#2c6cf7' } },
        moveHandleStyle: { color: '#2c6cf7' },
        // maxSpan: maxSpanPercent,
      },
    ],
    series: tmpSeries,
  }

  return option
})

const unCheckArr = ref<string[]>([])

const operatorMap = {
  '*': '×',
  '/': '÷',
}

function changeLegend(data: { name: string; selected: Record<string, boolean> }) {
  const { name, selected } = data
  if (!selected[name]) {
    unCheckArr.value.push(name)
  } else {
    unCheckArr.value = unCheckArr.value.filter(item => item !== name)
  }
}
</script>

<style scoped lang="scss">
.device-data-chart {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;

  .chart {
    width: 100%;
    height: 90%;
    min-height: 100px;
  }
}
</style>
