<script setup lang="ts">
import * as echarts from 'echarts/core';
import { PieChart, PieSeriesOption } from 'echarts/charts';
import {
  TitleComponent,
  // 组件类型的定义后缀都为 ComponentOption
  TitleComponentOption,
  TooltipComponent,
  TooltipComponentOption,
  GridComponent,
  GridComponentOption,
  // 数据集组件
  DatasetComponent,
  DatasetComponentOption,
  // 内置数据转换器组件 (filter, sort)
  TransformComponent,
} from 'echarts/components';
import { LabelLayout, UniversalTransition } from 'echarts/features';
import { CanvasRenderer } from 'echarts/renderers';
import { onMounted, PropType, watch, reactive, nextTick, computed } from 'vue';
import { IDiskCharts } from '@/model/System/monitor-interface';
import { colors } from '@/model/colors';
import mixins from '@/utils/watchSwitch';
import { getRealColor } from '@/utils/utils';
import useStore from '@/stores';

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

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


let { componentIsShowing } = mixins();
let doms: any = reactive([]);
let options: any = reactive([]);
let myCharts: any = [];

const props = defineProps({
  chartsData: {
    type: Array as PropType<IDiskCharts[]>,
    default: () => [],
    required: true,
  },
  thresholdPercent: {
    type: Number,
    default: 0,
    required: true,
  },
});

const watchArr = [() => props.chartsData, () => props.thresholdPercent];

watch(watchArr, () => {
  if (componentIsShowing.value) {
    networkCharts();
  }
});

const store = useStore();
const systemTheme = computed(() => {
  return store.state.loct.systemTheme;
});

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

function getSeriesData(diskData: any, color: string, shadowColor: string) {
  return [
    {
      value: diskData,
      itemStyle: {
        normal: {
          color: color,
          shadowColor: shadowColor,
          shadowBlur: 8,
          shadowOffsetY: 6,
        },
      },
      label: {
        normal: {
          show: true,
          position: 'center',
          width: 120,
          rich: {
            div: {
              fontSize: 32,
              lineHeight: 28,
              color: getRealColor('--o-text-color-primary'),
              fontWeight: 500,
            },
          },
          formatter: () => {
            return `{div|\n${diskData}}`;
          },
        },
      },
    },
    {
      value: 100 - diskData,
      itemStyle: {
        normal: {
          color: 'transparent',
        },
      },
    },
  ];
}

function getSeries(radius1: string, radius2: string, index: number): any {
  return {
    type: 'pie',
    radius: [radius1, radius2],
    center: ['50%', '50%'],
    cursor: 'pointer',
    hoverAnimation: false,
    startAngle: 90,
    silent: true,
    clockwise: true,
    label: {
      normal: {
        show: false,
      },
      emphasis: {
        show: false,
      },
    },
    labelLine: {
      normal: {
        show: false,
      },
    },
    data: [
      {
        value: 100,
        itemStyle: {
          normal: {
            color: colors.pieCircleColors[index],
          },
        },
      },
    ],
  };
}

function getOption(seriesData: any): ECOption {
  return {
    tooltip: {
      show: false,
    },
    series: [
      getSeries('0%', '71.42%', 0),
      getSeries('0%', '65.18%', 1),
      getSeries('0%', '53.57%', 2),
      {
        type: 'pie',
        radius: ['65.18%', '84.82%'],
        center: ['50%', '50%'],
        cursor: 'pointer',
        hoverAnimation: false,
        startAngle: 90,
        silent: true,
        clockwise: true,
        label: {
          normal: {
            show: false,
          },
          emphasis: {
            show: false,
          },
        },
        labelLine: {
          normal: {
            show: false,
          },
        },
        data: seriesData,
      },
    ],
  };
}

function networkCharts(): void {
  const { chartsData, thresholdPercent } = props;
  options.splice(0);
  doms.splice(0);
  if (chartsData) {
    chartsData.forEach((data: any) => {
      let diskData: any;
      let per = 0;
      const { UsedGB, CapacityGB } = data;
      if (typeof UsedGB === 'number' && typeof CapacityGB === 'number' && CapacityGB) {
        diskData = Math.ceil((UsedGB / CapacityGB) * 100);
        per = (UsedGB / CapacityGB) * 100;
      }
      let color = '';
      let shadowColor = '';
      if (diskData && per < thresholdPercent) {
        color = colors.heleathAndBeyondColors.heleathColor;
        shadowColor = colors.heleathAndBeyondColors.heleathShadowColor;
      } else {
        color = colors.heleathAndBeyondColors.beyondColor;
        shadowColor = colors.heleathAndBeyondColors.beyondShadowColor;
      }
      diskData = diskData || diskData === 0 ? diskData : '--';
      const seriesData = getSeriesData(diskData, color, shadowColor);
      const option: ECOption = getOption(seriesData);
      options.push(option);
    });

    nextTick(() => {
      options.forEach((e: any, i: number) => {
        if (myCharts[i]) {
          myCharts[i].clear();
          myCharts[i].setOption(e, true);
        } else {
          const myChart = echarts.init(doms[i]);
          myCharts[i] = myChart;
          myChart.setOption(e, true);
        }
      });
    });
  }
}

// 设置颜色
function setIconBgStyle(item: any) {
  const { thresholdPercent } = props;
  const { UsedGB, CapacityGB } = item;
  if (CapacityGB && (UsedGB / CapacityGB) * 100 >= thresholdPercent) {
    return 'background:' + colors.heleathAndBeyondColors.beyondColor;
  }
  return 'background:' + colors.heleathAndBeyondColors.heleathColor;
}

// 绑定ref
function setRef(dom: any) {
  doms.push(dom);
}

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

<template>
  <div class="disk-chart-box">
    <div v-for="(item, i) in options" :key="i" class="monitor-chart">
      <div class="monitor-info">
        <div class="used">
          <div class="icon" :style="setIconBgStyle(chartsData[i])"></div>
          <div class="text-box">
            <div>{{ chartsData[i].UsedGB }}GB</div>
            <div class="label">
              {{ $t('MOINTOR_HAS_USED') }}
            </div>
          </div>
        </div>
        <div class="unused">
          <div class="icon"></div>
          <div class="text-box">
            <div>{{ chartsData[i].CapacityGB }}GB</div>
            <div class="label">
              {{ $t('MOINTOR_TOTAL_SYSTEM_MEMORY_CAP') }}
            </div>
          </div>
        </div>
      </div>

      <div class="echart-info">
        <div :ref="setRef" class="monitor-option"></div>
        <div class="partition-name" :title="chartsData[i].PartitionName">
          <span class="key">{{ chartsData[i].PartitionName }}</span>
          <span>(%)</span>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
.disk-chart-box {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: flex-start;
  padding: 0 11px;
  color: var(--o-text-color-secondary);
  font-size: 12px;

  .monitor-chart {
    width: 25%;
    padding: 0 40px;
    display: flex;
    align-items: center;

    .echart-info {
      flex: 1;
      display: flex;
      flex-direction: column;
      justify-content: center;
      position: relative;
      height: 224px;

      .monitor-option {
        width: 100%;
        height: 100%;
      }
      .partition-name {
        position: absolute;
        top: 80px;
        left: 50%;
        z-index: 99;
        transform: translate(-50%, 0);
        font-size: 16px;
        color: var(--o-text-color-secondary);
        display: flex;
        align-items: center;
        justify-content: center;

        .key {
          max-width: 80px;
          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
        }
      }
    }

    .monitor-info {
      display: inline-block;
      margin-right: 8px;

      .icon {
        margin-top: 3px;
        margin-right: 8px;
        display: inline-block;
        width: 12px;
        height: 12px;
        border-radius: 6px;
        background: var(--o-border-color-light);
      }

      .used {
        display: flex;
        align-items: flex-start;
        margin-bottom: 16px;
      }

      .unused {
        display: flex;
      }

      .label {
        white-space: nowrap;
      }
    }
  }
}
</style>
