<script lang="ts" setup>
import { nextTick, watch, onMounted, onBeforeUnmount, ref, markRaw } from 'vue';
import * as echarts from 'echarts/core';
import {
  TitleComponent,
  ToolboxComponent,
  TooltipComponent,
  GridComponent,
  DataZoomComponent,
  LegendComponent,
} from 'echarts/components';
import { LineChart } from 'echarts/charts';
import { UniversalTransition } from 'echarts/features';
import { CanvasRenderer } from 'echarts/renderers';
import { parseSizeFromKBs, parseSizeFromMB } from '@/utils/parse-utils';

echarts.use([
  TitleComponent,
  ToolboxComponent,
  TooltipComponent,
  GridComponent,
  DataZoomComponent,
  LegendComponent,
  LineChart,
  CanvasRenderer,
  UniversalTransition,
]);

const props = defineProps({
  /**
   * 图表主题
   *
   * 'dark' | 'light'
   */
  theme: {
    type: String,
    default: 'light', // 'dark' | 'light'
  },
  /**宽度，默认100% */
  width: {
    type: String,
    default: '100%',
  },
  /**高度 */
  height: {
    type: String,
    default: '200px',
  },
  /**底部时间轴 */
  dataZoom: {
    type: Boolean,
    default: false,
  },
  /**
   * option: { title , xDatas, yDatas, formatStr, yAxis, grid, tooltip}
   *
   * grid 图偏移 列如{ left: '15%', right: '15%', bottom: '20%' }
   * formatStr 支持 'KB/s'、'MB'、自定义格式
   */
  option: {
    type: Object,
    required: true,
  },
});

const seriesStyle = [
  {
    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
      {
        offset: 0,
        color: 'rgba(22, 119, 255, .5)',
      },
      {
        offset: 1,
        color: 'rgba(22, 119, 255, 0)',
      },
    ]),
  },
  {
    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
      {
        offset: 0,
        color: 'rgba(82, 196, 26, .5)',
      },
      {
        offset: 1,
        color: 'rgba(82, 196, 26, 0)',
      },
    ]),
  },
  {
    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
      {
        offset: 0,
        color: 'rgba(250, 173, 20, .5)',
      },
      {
        offset: 1,
        color: 'rgba(250, 173, 20, 0)',
      },
    ]),
  },
  {
    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
      {
        offset: 0,
        color: 'rgba(255, 77, 79, 0.5)',
      },
      {
        offset: 1,
        color: 'rgba(255, 77, 79, 0)',
      },
    ]),
  },
];

let newChart: echarts.ECharts;
const chartDom = ref<HTMLElement | undefined>(undefined);

/**初始化渲染图表 */
function handleRanderChart(container: HTMLElement | undefined) {
  if (!container || !props.option.yDatas) return;
  if (!newChart) {
    newChart = markRaw(echarts.init(container, props.theme));
  }

  const series: any = [];
  const yDatasLen = props.option.yDatas.length;
  props.option.yDatas.forEach((item: any, index: number) => {
    series.push({
      name: item?.name,
      type: 'line',
      areaStyle: seriesStyle[index % yDatasLen],
      data: item?.data,
      showSymbol: false,
      yAxisIndex: item.yAxisIndex ? 1 : null,
    });
  });

  // 右侧y轴辅助线
  const yAxis: any = [];
  if (props.option.yAxis && props.option.yAxis.length > 0) {
    props.option.yAxis.forEach((item: any) => {
      yAxis.push({
        splitLine: {
          show: true,
          //分隔辅助线
          lineStyle: {
            type: 'dashed', //线的类型 虚线0
            opacity: props.theme === 'dark' ? 0.1 : 1, //透明度
          },
        },
        ...item,
      });
    });
  }

  // 把配置和数据放这里
  const option = {
    title: [
      {
        left: 'center',
        text: props.option.title,
        show: props.option.title,
      },
    ],
    zlevel: 1,
    z: 1,
    tooltip: props.option.tooltip || {
      trigger: 'axis',
      formatter: function (datas: any) {
        let res = datas[0].name + '<br/>';
        // 拼接值的格式
        switch (props.option.formatStr) {
          case 'KB/s':
            for (const item of datas) {
              res += `${item.marker} ${item.seriesName}：${parseSizeFromKBs(
                item.data
              )}<br/>`;
            }
            break;
          case 'MB':
            for (const item of datas) {
              res += `${item.marker} ${item.seriesName}：${parseSizeFromMB(
                item.data
              )}<br/>`;
            }
            break;
          default:
            for (const item of datas) {
              res += `${item.marker} ${item.seriesName}：${item.data}${props.option.formatStr}<br/>`;
            }
            break;
        }
        return res;
      },
    },
    grid: props.option.grid || { left: '8%', right: '8%', bottom: '20%' },
    legend: props.option.legend || {
      right: 10,
      itemWidth: 8,
      textStyle: {
        color: '#646A73',
      },
      icon: 'circle',
    },
    xAxis: { data: props.option.xDatas, boundaryGap: false },
    yAxis: props.option.yAxis
      ? yAxis
      : {
          name: '( ' + props.option.formatStr + ' )',
          splitLine: {
            //分隔辅助线
            lineStyle: {
              type: 'dashed', //线的类型 虚线0
              opacity: props.theme === 'dark' ? 0.1 : 1, //透明度
            },
          },
        },
    series: series,
    dataZoom: [{ startValue: props.option?.xDatas[0], show: props.dataZoom }],
  };

  // 渲染数据
  option && newChart.setOption(option, true);

  // 创建 ResizeObserver 实例
  var observer = new ResizeObserver(entries => {
    if (newChart) {
      newChart.resize();
    }
  });
  // 监听元素大小变化
  observer.observe(container);
}

watch(
  () => props.option,
  val => {
    if (val) {
      nextTick(() => {
        handleRanderChart(chartDom.value);
      });
    }
  }
);

onMounted(() => {
  nextTick(() => {
    handleRanderChart(chartDom.value);
  });
});

onBeforeUnmount(() => {
  newChart?.dispose();
});
</script>

<template>
  <div ref="chartDom" :style="{ height: height, width: width }"></div>
</template>

<style lang="less" scoped></style>
