<script setup lang="ts">
import useStore from '@/stores';
import { onMounted, PropType, watch, ref, computed } from 'vue';
import { IChartsData } from '@/model/System/monitor-interface';
import { htmlEncode, initLeftDistance } from '@/pages/System/Monitor/monitorFunctions';
import '@/assets/common/style/echarts-formatter-style/index.scss';
import { visualMapLineColor, colors } from '@/model/colors';
import mixins from '@/utils/watchSwitch';
import { getStoreData } from '@/utils/composition';

import * as echarts from 'echarts/core';
import { LineChart, LineSeriesOption } from 'echarts/charts';
import {
  TitleComponent,
  // 组件类型的定义后缀都为 ComponentOption
  TitleComponentOption,
  TooltipComponent,
  TooltipComponentOption,
  GridComponent,
  GridComponentOption,
  // 数据集组件
  DatasetComponent,
  DatasetComponentOption,
  // 内置数据转换器组件 (filter, sort)
  TransformComponent,
  VisualMapComponent,
  MarkLineComponent,
} from 'echarts/components';
import { LabelLayout, UniversalTransition } from 'echarts/features';
import { CanvasRenderer } from 'echarts/renderers';
import { getRealColor, getThemeMode } from '@/utils/utils';
import { showCircles } from '@/model/echartsCircles';
import { traduction } from '@/utils/language';

// 通过 ComposeOption 来组合出一个只有必须组件和图表的 Option 类型
type ECOption = echarts.ComposeOption<
| LineSeriesOption
| TitleComponentOption
| TooltipComponentOption
| GridComponentOption
| DatasetComponentOption
>;

// 注册必须的组件
echarts.use([
  VisualMapComponent,
  TitleComponent,
  TooltipComponent,
  GridComponent,
  MarkLineComponent,
  DatasetComponent,
  TransformComponent,
  LineChart,
  LabelLayout,
  UniversalTransition,
  CanvasRenderer,
]);

let { componentIsShowing } = mixins();
const store = useStore();
const systemTheme = computed(() => {
  return store.state.loct.systemTheme;
});
const multihost = computed(() => getStoreData('loct', 'multihost'));

let myChart: any = null;
const chartDom = ref();
const props = defineProps({
  title: {
    type: String,
    default: '',
    required: true,
  },
  type: {
    type: String,
    default: '',
    required: true,
  },
  showData: {
    type: Object as PropType<IChartsData>,
    default: () => {
      return {
        xData: [],
        seriesData: [],
      };
    },
    required: true,
  },
  systemId: {
    type: Number,
    default: 0,
    required: false,
  },
});

let thresholdPercent = 0;

const watchArr = [
  () => props.showData.ThresholdPercent,
  () => props.showData.History,
  () => props.title,
  () => props.type,
];
watch(watchArr, () => {
  if (componentIsShowing.value) {
    singleWireCharts();
  }
});

watch(systemTheme, () => {
  if (componentIsShowing.value) {
    singleWireCharts();
  }
});

function initThresholdPercent() {
  if (typeof props.showData.ThresholdPercent === 'string') {
    thresholdPercent = parseInt(props.showData.ThresholdPercent);
  } else {
    thresholdPercent = props.showData.ThresholdPercent || 0;
  }
}

function yAxis(): any {
  return {
    type: 'value',
    axisLine: {
      show: false,
    },
    splitLine: {
      lineStyle: {
        type: 'dashed',
        color: getRealColor('--o-border-color-base'),
      },
    },
    offset: 2,
    axisTick: {
      show: false,
    },
    axisLabel: {
      margin: 8,
      textStyle: {
        align: 'right',
        verticalAlign: 'middle',
        color: getRealColor('--o-text-color-tertiary'),
        fontSize: 12,
      },
      // 刚好是门限值的刻度不显示,这样门限值的数值就不会与刻度值重叠
      formatter: (value: any, index: number) => {
        const str = props.showData.ThresholdPercent;
        if (str || str === 0) {
          if (
            (typeof str === 'number' && str === value) ||
            (typeof str === 'string' && parseInt(str) === value)
          ) {
            return '';
          }
        }
        return value;
      },
    },
    splitNumber: 4,
  };
}

function getXaxis(xData: any): any {
  return {
    show: true,
    type: 'category',
    boundaryGap: false,
    axisLine: {
      show: true,
      lineStyle: {
        width: 1,
        type: 'solid',
        color: getRealColor('--o-border-color-light'),
      },
    },
    axisTick: {
      show: false,
    },
    axisLabel: {
      margin: 10,
      color: getRealColor('--o-text-color-tertiary'),
      fontSize: 12,
      formatter(v: any) {
        return v.slice(5).replace(' ', '\n');
      },
    },
    splitLine: {
      show: false,
    },
    data: xData,
  };
}

// 判断所有的数据是否都等于门限值,进而控制是否展示门限值的虚线
function showMarkLine(yData: any[]) {
  return !yData.every((item: number) => {
    return item === thresholdPercent;
  });
}

// 获取区域面积渐变
function getAreaStyle(yData: any) {
  const max = Math.max.call(null, ...yData);
  if (max < thresholdPercent) {
    return {
      opacity: 0.15,
      color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
        {
          offset: 0,
          color: colors.heleathAndBeyondColors.heleathColor,
        },
        {
          offset: 1,
          color: '#fff',
        },
      ]),
    };
  } else {
    // 当前y轴没有设置最大值，所以可以用数据的最大值代表y轴的最大值,如果y轴设置了最大值，那就需要用y轴最大值,注意0不能作为除数
    return {
      opacity: 0.15,
      color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
        {
          offset: 0,
          color: colors.heleathAndBeyondColors.beyondColor,
        },
        {
          offset: max === 0 ? 1 : 1 - (thresholdPercent / max),
          color: colors.heleathAndBeyondColors.beyondColor,
        },
        {
          offset: max === 0 ? 1 : 1 - (thresholdPercent / max),
          color: colors.heleathAndBeyondColors.heleathColor,
        },
        {
          offset: 1,
          color: '#fff',
        },
      ]),
    };
  }
}

function getSeries(yData: any, flag: boolean): any {
  return [
    {
      name: '',
      type: 'line',
      smooth: false,
      showSymbol: false,
      symbolSize: 12,
      symbol: (value: any) => {
        if (thresholdPercent <= value) {
          return 'image://' + showCircles.redCircle;
        }
        return 'image://' + showCircles.normalCircles[0];
      },
      markLine: {
        silent: false,
        symbol: 'none',
        lineStyle: {
          width: 1,
          color: flag ? visualMapLineColor : 'rgba(0, 0, 0, 0)',
        },
        label: {
          show: true,
          position: 'start',
          distance: [initLeftDistance(String(thresholdPercent).length), 0],
          color: visualMapLineColor,
          fontSize: 16,
          fontWeight: '500',
        },
        data: [
          {
            name: thresholdPercent,
            yAxis: thresholdPercent,
            symbol: 'none',
          },
        ],
      },
      lineStyle: {
        width: 2,
      },
      areaStyle: getAreaStyle(yData),
      data: yData,
    },
  ];
}

function getVisualMap(flag: boolean) {
  return {
    show: false,
    pieces: [
      {
        gte: 0,
        lt: thresholdPercent,
        // 如果所有展示数据和门限值是同一个值的时候只展示一条红色的横线
        color: flag ? colors.heleathAndBeyondColors.heleathColor : colors.heleathAndBeyondColors.beyondColor,
      },
      {
        gte: thresholdPercent,
        lte: 100,
        color: colors.heleathAndBeyondColors.beyondColor,
      },
    ],
  };
}

function getTitle(): any {
  return {
    text: props.title,
    textStyle: {
      color: getRealColor('--o-text-color-secondary'),
      fontWeight: 'normal',
      fontSize: '12px',
      fontFamily: 'HarmonyOS Sans SC Medium',
    },
    left: '-5px',
    top: '-4px',
  };
}

function getToolTip(): any {
  const tipBgColor = getThemeMode() === 'light' ? '#FFF' : '#2A2F37';
  return {
    trigger: 'axis',
    backgroundColor: tipBgColor,
    borderColor: tipBgColor,
    extraCssText: 'padding:8px 16px; border-radius:1px;',
    axisPointer: {
      z: 1,
      lineStyle: {
        type: 'solid',
        width: 2,
        color: getRealColor('--o-border-color-base'),
      },
    },
    formatter: (param: any) => {
      let sp = '<span class="echarts-formatter-block cpu"></span>';
      let className = 'cpu';
      if (param[0].seriesIndex === 0) {
        if (param[0].data >= 0 && param[0].data < thresholdPercent) {
          className = showMakeLine.value ? 'cpu': 'red';
        } else if (param[0].data >= thresholdPercent && param[0].data<=100) {
          className = 'red';
        }
      }
      sp = `<span class="echarts-formatter-block ${className}"></span>`;
      return `<span class="echarts-formatter-first-row">${htmlEncode(param[0].axisValue)}</span><br>
                  <div class="echarts-formatter-other-row-value-box">
                    ${sp}
                    <span class="echarts-formatter-key">
                      ${(props.type === traduction('MONITOR_CPU_USAGE') && multihost.value) ?
    (multihost.value ? traduction('BMC_LOG_HOST') + props.systemId : '') + ' ' + traduction('MONITOR_CPU_USAGE') :
    props.type
}</span>
                    <span class="echarts-formatter-value">${htmlEncode(param[0].data)}</span>
                  </div>
                `;
    },
  };
}
let showMakeLine = ref(false);
function singleWireCharts(): void {
  initThresholdPercent();
  const { showData } = props;
  const { History } = showData;

  let xData: string[] = [];
  let yData: number[] = [];
  if (History) {
    // CPU和内存返回的用于绘制图表的字段不一样
    const key = props.type === traduction('MONITOR_CPU_USAGE') ? 'CpuUtilisePercents' : 'MemOSUtilisePercents';
    History.forEach((item: any) => {
      xData.push(item.Time);
      yData.push(item[key]);
    });
  }
  showMakeLine.value = showMarkLine(yData);
  const option: ECOption = {
    title: getTitle(),
    tooltip: getToolTip(),
    visualMap: getVisualMap(showMakeLine.value),
    xAxis: getXaxis(xData),
    yAxis: yAxis(),
    grid: {
      borderWidth: 0,
      left: 12,
      top: props.title ? 36 : 12,
      right: 12,
      bottom: 0,
      containLabel: true,
    },
    series: getSeries(yData, showMakeLine.value),
  };

  if (myChart) {
    myChart.clear();
    myChart.setOption(option, true);
  } else {
    myChart = echarts.init(chartDom.value);
    myChart.setOption(option, true);
  }
}

onMounted(() => {
  singleWireCharts();
});
</script>

<template>
  <div ref="chartDom" class="chart"></div>
</template>

<style scoped lang="scss">
.chart {
  height: 100%;
}
</style>
