<script setup lang="ts">
import { onMounted, ref, nextTick, watch } from 'vue';
import * as echarts from 'echarts/core';
import { GridComponent, TooltipComponent } from 'echarts/components';
import { CanvasRenderer } from 'echarts/renderers';
import { graphNodeClickID, graphNodeState } from '../../hooks/useTopology';
import useI18n from '@/hooks/useI18n';
import { markRaw } from 'vue';
// 引入液体填充图表
import 'echarts-liquidfill';

const { t } = useI18n();

echarts.use([GridComponent, TooltipComponent, CanvasRenderer]);

/**图DOM节点实例对象 */
const neResourcesDom = ref<HTMLElement | undefined>(undefined);

/**图实例对象 */
const neResourcesChart = ref<any>(null);

// 当前选中的网元ID
const currentNeId = ref('');

// 资源数据
const resourceData = ref({
  neCpu: 1,
  sysCpu: 1,
  sysMem: 1,
  sysDisk: 1,
});

// 获取颜色
function getColorByValue(value: number) {
  if (value >= 70) {
    return ['#f5222d', '#ff7875']; // 红色
  } else if (value >= 30) {
    return ['#2f54eb', '#597ef7']; // 蓝色
  } else {
    return ['#52c41a', '#95de64']; // 绿色
  }
}

/**图数据 */
const optionData: any = {
  tooltip: {
    trigger: 'item',
    // formatter: '{a}: {c}%',
    formatter: (params: any) => {
      return `${params.seriesName}: ${(params.value * 100).toFixed(2)}%`;
    },
  },
  grid: {
    top: '10%',
    bottom: '5%',
    left: '5%',
    right: '5%',
    containLabel: true,
  },
  series: [
    {
      type: 'liquidFill',
      radius: '50%',
      center: ['15%', '35%'],
      data: [resourceData.value.neCpu / 100],
      name: t('views.dashboard.overview.resources.neCpu'),
      color: getColorByValue(resourceData.value.neCpu),
      backgroundStyle: {
        color: 'rgba(10, 60, 160, 0.1)',
      },
      label: {
        normal: {
          formatter: () => {
            return `${t('views.dashboard.overview.resources.neCpu')}\n${
              resourceData.value.neCpu
            }%`;
          },
          textStyle: {
            fontSize: 12,
            color: '#fff',
          },
        },
      },
      outline: {
        show: true,
        borderDistance: 2,
        itemStyle: {
          borderColor: '#0a3ca0',
          borderWidth: 1,
        },
      },
    },
    {
      type: 'liquidFill',
      radius: '50%',
      center: ['85%', '35%'],
      data: [resourceData.value.sysCpu / 100],
      name: t('views.dashboard.overview.resources.sysCpu'),
      color: getColorByValue(resourceData.value.sysCpu),
      backgroundStyle: {
        color: 'rgba(10, 60, 160, 0.1)',
      },
      label: {
        normal: {
          formatter: () => {
            return `${t('views.dashboard.overview.resources.sysCpu')}\n${
              resourceData.value.sysCpu
            }%`;
          },
          textStyle: {
            fontSize: 12,
            color: '#fff',
          },
        },
      },
      outline: {
        show: true,
        borderDistance: 2,
        itemStyle: {
          borderColor: '#0a3ca0',
          borderWidth: 1,
        },
      },
    },
    {
      type: 'liquidFill',
      radius: '50%',
      center: ['35%', '65%'],
      data: [resourceData.value.sysMem / 100],
      name: t('views.dashboard.overview.resources.sysMem'),
      color: getColorByValue(resourceData.value.sysMem),
      backgroundStyle: {
        color: 'rgba(10, 60, 160, 0.1)',
      },
      label: {
        normal: {
          formatter: () => {
            return `${t('views.dashboard.overview.resources.sysMem')}\n${
              resourceData.value.sysMem
            }%`;
          },
          textStyle: {
            fontSize: 12,
            color: '#fff',
          },
        },
      },
      outline: {
        show: true,
        borderDistance: 2,
        itemStyle: {
          borderColor: '#0a3ca0',
          borderWidth: 1,
        },
      },
    },
    {
      type: 'liquidFill',
      radius: '50%',
      center: ['65%', '65%'],
      data: [resourceData.value.sysDisk / 100],
      name: t('views.dashboard.overview.resources.sysDisk'),
      color: getColorByValue(resourceData.value.sysDisk),
      backgroundStyle: {
        color: 'rgba(10, 60, 160, 0.1)',
      },
      label: {
        normal: {
          formatter: () => {
            return `${t('views.dashboard.overview.resources.sysDisk')}\n${
              resourceData.value.sysDisk
            }%`;
          },
          textStyle: {
            fontSize: 12,
            color: '#fff',
          },
        },
      },
      outline: {
        show: true,
        borderDistance: 2,
        itemStyle: {
          borderColor: '#0a3ca0',
          borderWidth: 1,
        },
      },
    },
  ],
};

/**图数据渲染 */
function handleRanderChart(container: HTMLElement | undefined, option: any) {
  if (!container) return;
  neResourcesChart.value = markRaw(echarts.init(container));
  option && neResourcesChart.value.setOption(option);

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

function fnChangeData(data: any[], itemID: string) {
  const neType = itemID.split('_')[0];
  const neID = itemID.split('_')[1];
  currentNeId.value = neID;

  let info = data.find((item: any) => item.id === neType);
  if (!info || !info.neStateMap[neID]?.online) return;

  let sysCpuUsage = 0;
  let nfCpuUsage = 0;
  if (info.neStateMap[neID].cpu) {
    nfCpuUsage = info.neStateMap[neID].cpu.nfCpuUsage;
    const nfCpu = +(info.neStateMap[neID].cpu.nfCpuUsage / 100);
    nfCpuUsage = +nfCpu.toFixed(2);
    if (nfCpuUsage > 100) {
      nfCpuUsage = 100;
    }

    sysCpuUsage = info.neStateMap[neID].cpu.sysCpuUsage;
    let sysCpu = +(info.neStateMap[neID].cpu.sysCpuUsage / 100);
    sysCpuUsage = +sysCpu.toFixed(2);
    if (sysCpuUsage > 100) {
      sysCpuUsage = 100;
    }
  }

  let sysMemUsage = 0;
  if (info.neStateMap[neID].mem) {
    const men = info.neStateMap[neID].mem.sysMemUsage;
    sysMemUsage = +(men / 100).toFixed(2);
    if (sysMemUsage > 100) {
      sysMemUsage = 100;
    }
  }

  let sysDiskUsage = 0;
  if (
    info.neStateMap[neID].disk &&
    Array.isArray(info.neStateMap[neID].disk.partitionInfo)
  ) {
    let disks: any[] = info.neStateMap[neID].disk.partitionInfo;
    disks = disks.sort((a, b) => +b.used - +a.used);
    if (disks.length > 0) {
      const { total, used } = disks[0];
      sysDiskUsage = +((used / total) * 100).toFixed(2);
    }
  }

  resourceData.value = {
    neCpu: nfCpuUsage,
    sysCpu: sysCpuUsage,
    sysMem: sysMemUsage,
    sysDisk: sysDiskUsage,
  };

  // 更新图表数据
  neResourcesChart.value.setOption({
    series: [
      {
        data: [resourceData.value.neCpu / 100],
        color: getColorByValue(resourceData.value.neCpu),
        label: {
          normal: {
            formatter: () => {
              return `${t('views.dashboard.overview.resources.neCpu')}\n${
                resourceData.value.neCpu
              }%`;
            },
          },
        },
      },
      {
        data: [resourceData.value.sysCpu / 100],
        color: getColorByValue(resourceData.value.sysCpu),
        label: {
          normal: {
            formatter: () => {
              return `${t('views.dashboard.overview.resources.sysCpu')}\n${
                resourceData.value.sysCpu
              }%`;
            },
          },
        },
      },
      {
        data: [resourceData.value.sysMem / 100],
        color: getColorByValue(resourceData.value.sysMem),
        label: {
          normal: {
            formatter: () => {
              return `${t('views.dashboard.overview.resources.sysMem')}\n${
                resourceData.value.sysMem
              }%`;
            },
          },
        },
      },
      {
        data: [resourceData.value.sysDisk / 100],
        color: getColorByValue(resourceData.value.sysDisk),
        label: {
          normal: {
            formatter: () => {
              return `${t('views.dashboard.overview.resources.sysDisk')}\n${
                resourceData.value.sysDisk
              }%`;
            },
          },
        },
      },
    ],
  });
}

watch(
  graphNodeState,
  v => {
    fnChangeData(v, graphNodeClickID.value);
  },
  {
    deep: true,
  }
);

watch(graphNodeClickID, v => {
  fnChangeData(graphNodeState.value, v);
});

onMounted(() => {
  nextTick(() => {
    handleRanderChart(neResourcesDom.value, optionData);
  });
});
</script>

<template>
  <div class="resource-panel">
    <div ref="neResourcesDom" class="chart"></div>
  </div>
</template>

<style lang="less" scoped>
.resource-panel {
  width: 100%;
  height: 100%;
  margin-top: -32px;
  display: flex;
  flex-direction: column;

  .panel-title {
    font-size: 14px;
    color: #00fcff;
    padding: 8px;
    border-bottom: 1px solid rgba(10, 115, 255, 0.3);
  }

  .chart {
    flex: 1;
    width: 100%;
  }
}
</style>
