<!--
 * @Author: tqh
 * @FilePath: /yuan-flow-threat-collector-browser/src/components/chart/CircularDiagram/CircularDiagram.vue
 * @Date: 2023-4-27 11:18:00
 * @Description: 
 * @LastEditTime: 2023-06-05 11:15:50
-->
<script setup lang="ts">
import { ref, defineProps, watchEffect, unref, onMounted, computed, watch, nextTick } from "vue";
import type { EChartsOption } from "echarts";
import { useECharts } from "../../../hooks/web/useECharts";
import {
  themeColor,
  colorList,
  mergeOptions,
  getThemeColor,
  securityColorList,
} from "../../../components/chart/options/index";
import { isObject } from "../../../utils/is";
import { bigNumberTransform } from "../../../utils/utils";
const chartRef = ref<HTMLDivElement | null>(null);
const { setOptions, getInstance, echarts } = useECharts(
  chartRef as ref<HTMLDivElement>
);

/**
 * @author changjun
 * @description 基础组件-环形图组件
 * @prop { String } name 关联图表的series
 * @prop { Array } chartData 图表数据
 * @prop { Boolean } manual 手动设置 结合otherOptions
 * @prop { Object } otherOptions 手动设置一些其它的设置 结合manual
 * @prop { Function } legendFormatter 图例自定义显示函数
 * @date 2022/08/29
 */

/**
 * @desc: 环形图图表组件
 * @author: changjun
 */

interface CircularDiagramChartProps {
  /**
   * 名称，关联图表的 series
   */
  name: string;
  /**
   * 图表数据
   */
  chartData: any[];
  tooltipValueFormatter?: any;
  /**
   * 格式化图例显示函数 用于需要显示图例名称之外内容的时候
   */
  legendFormatter?: string | ((name: string) => string);
  /**
   * 是否需要手动设置一些其它的设置，需要结合otherOptions才能起作用
   */
  manual?: boolean;
  pieCenter?: string[];
  radius?: string[];
  /**
   * 手动设置一些其它的设置，需要结合manual才能起作用
   */
  otherOptions?: EChartsOption;
  legendLeft?: string;
  legendRight?: string;
  legendTop?: string;
  labelWidth?: string;
  chartClass?: string;
  legendClass?: string;
  legendLayout?: string;
  otherType?: string;
  colorBg?: any[];
  titleText?: string;
  titleSubText?: string;
  tooltipFormatter?:
    | string
    | ((params: any, ticket: any, callback: any) => string);
  chartWidth?: string;
  tooltipBgColor?: string;
  showLabel?: boolean;
  itemStyle?: string;
}

const {
  name = "",
  chartData = [],
  legendFormatter = (name) => name,
  manual = false,
  otherOptions = {},
  pieCenter = ["25%", "50%"],
  radius = ["50%", "70%"],
  chartClass = "",
  legendClass = "",
  labelWidth = "default",
  legendLeft = "0",
  legendRight = "0",
  legendTop = "35%",
  legendLayout = "horizontal",
  otherType = "default",
  colorBg = colorList,
  titleText = "",
  titleSubText = "",
  tooltipFormatter = "",
  tooltipValueFormatter = (val) => val,
  chartWidth = "50%",
  tooltipBgColor = "transparent",
  showLabel = true,
  itemStyle = "#EFEFEF",
} = defineProps<CircularDiagramChartProps>();

let options: EChartsOption = {
  title: {
    text: unref(titleText),
    subtext: unref(titleSubText),
    left: "48%",
    top: "45%",
    x: "center",
    textAlign: "center",
    textStyle: {
      color: "rgba(0, 0, 0, 0.2)",
      fontSize: 16,
      align: "center",
    },
    subtextStyle: {
      color: "rgba(0, 0, 0, 0.4)",
      fontSize: 32,
      align: "center",
    },
  },

  tooltip: {
    show: true,
    borderColor: "transparent",
    backgroundColor: unref(tooltipBgColor),
    valueFormatter: unref(tooltipValueFormatter),
    extraCssText: "border-radius: 4px;",
    trigger: "item",
    position: "top",
  },

  color: colorBg,

  grid: {
    top: "5%",
  },

  legend: {
    show: false,
    top: "middle",
    left: "middle",
    orient: "vertical",
    itemGap: 25,
    icon: "circle",
    backgroundColor: "transparent",
    itemWidth: 8,
    itemHeight: 8,
    height: "65%",
    padding: [0, 0, 0, 0],
    textStyle: {
      rich: {
        subtitle: {
          fontSize: 12,
          color: "rgba(0,0,0,0.4)",
          padding: [0, 0, 0, 20],
          align: "right",
          width: 70,
        },
        title: {
          fontSize: 14,
          color: "rgba(0,0,0,0.65)",
          backgroundColor: "transparent",
        },
      },
      color: "rgba(0,0,0,0.65)",
      fontSize: "14px",
    },
  },

  series: [
    {
      name: "",
      type: "pie",
      center: unref(pieCenter),
      radius: unref(radius),
      label: {
        show: false,
      },
      data: chartData,
      showEmptyCircle: true,
      emptyCircleStyle: {
        color: "#ddd",
      },
    },
  ],
};
/**
 * @description: 判断数据是不是为0
 */
const isAllNumPosive = (array) => {
  return array.every((item) => item.value === 0);
};
let activeList = ref([]) as any; // 定义一个激活的状态表
const initChartDataActiveList = () => {
  const list = unref(chartData).map((item) => {
    return item.name;
  });
  activeList.value = list;
};

async function initChart() {
  options.series![0].name = unref(name);
  options.series![0].data = isAllNumPosive(unref(chartData))
    ? [{ value: 0, name: "暂无数据", itemStyle: { color: unref(itemStyle) } }]
    : unref(chartData);
  options.title.subtext = unref(titleSubText);
  // @ts-ignore
  options.legend!.formatter = unref(legendFormatter);
  options.series![0].center = unref(pieCenter);
  options.series![0].radius = unref(radius);
  // 如果是手动设置模式的话
  if (unref(manual) && isObject(unref(otherOptions))) {
    options = mergeOptions(options, unref(otherOptions));
  }
  if (unref(tooltipFormatter)) {
    // @ts-ignore
    options.tooltip!.formatter = unref(tooltipFormatter);
  }
  console.log(options);
  if (unref(titleText)) {
    if (options.series![0].data[0].name == "暂无数据") {
      options.title.text = unref(titleText);
    } else {
      options.title.text = "";
    }
  }
  initChartDataActiveList();
  setOptions(options);
}

onMounted(() => {
  initChart();
});

watchEffect(() => {
  initChart();
});

const handleClick = (name) => {
  const instance = getInstance();
  if (instance) {
    instance.dispatchAction({
      type: "legendToggleSelect",
      name: name,
    });
    if (unref(activeList).includes(name)) {
      activeList.value = unref(activeList).filter((item) => item !== name);
    } else {
      activeList.value = [...unref(activeList), name];
    }
  }
};
const handleHover = (name) => {
  const instance = getInstance();
  if (instance) {
    instance.dispatchAction({
      type: "highlight",
      name: name,
    });
  }
};

const handleHoverLeave = (name) => {
  const instance = getInstance();
  if (instance) {
    instance.dispatchAction({
      type: "downplay",
      name: name,
    });
  }
};

const getLabelWidth = computed(() => {
  return unref(labelWidth) === "default" ? "width-default" : "width-self";
});

const getLegendStyle = computed(() => {
  const _style = {
    right: unref(legendRight),
    top: unref(legendTop),
  } as any;
  if (unref(legendLeft) !== "0") {
    _style.left = unref(legendLeft);
  }
  return _style;
});

const getLegendClass = computed(() => {
  let _class = `${unref(legendClass)}`;
  if (unref(legendLayout) === "vertical") {
    _class += " legend-vertical";
  }
  return _class;
});
const resetColor = (val) => {
  let item = colorList.find((item) => item.name == val);
  if (item) {
    return item.color;
  }
};
</script>

<template>
  <div
    class="chart-flex"
    v-if="otherType != 'five'"
    :class="chartData.length == 0 ? 'jstcontent' : ''"
  >
    <div
      class="chart"
      :class="chartClass"
      ref="chartRef"
      :style="{ width: chartWidth, height: '100%' }"
    ></div>
    <div
      v-if="otherType == 'default'"
      class="custom-circle-legend"
      :class="getLegendClass"
      :style="getLegendStyle"
    >
      <div
        class="custom-circle-legend-item"
        @mouseover="handleHover(item.name)"
        @mouseleave="handleHoverLeave(item.name)"
        :class="activeList.includes(item.name) ? 'is-active' : 'is-unactive'"
        v-for="(item, index) in chartData"
        @click="handleClick(item.name)"
      >
        <div
          class="circle-icon"
          :style="{
            background: activeList.includes(item.name)
              ? colorBg[index]
              : '#ddd',
          }"
        ></div>
        <div class="circle-icon-flex">
          <div
            class="legend-label ya-primary-text"
            :class="{
              getLabelWidth,
              'ya-primary-text': activeList.includes(item.name),
            }"
          >
            {{ item.name }}
          </div>
          <div
            class="legend-value ya-regular-text"
            :class="{ 'ya-regular-text': activeList.includes(item.name) }"
          >
            {{ item.valueFormat || item.value
            }}<span v-if="item.unit">（{{ item.unit }}）</span>
          </div>
        </div>
      </div>
    </div>
    <div
      v-if="otherType == 'two'"
      class="custom-circle-legend"
      :class="getLegendClass"
      :style="getLegendStyle"
    >
      <div
        class="custom-circle-legend-item"
        @mouseover="handleHover(item.name)"
        @mouseleave="handleHoverLeave(item.name)"
        :class="activeList.includes(item.name) ? 'is-active' : 'is-unactive'"
        v-for="(item, index) in chartData"
        @click="handleClick(item.name)"
      >
        <div
          class="circle-icon"
          :style="{
            background: activeList.includes(item.name)
              ? colorBg[index]
              : '#ddd',
          }"
        ></div>
        <div>
          <div class="ya-primary-text" :class="getLabelWidth">
            <CustomTooltip
              :show="true"
              :text="item.name"
              :placement="'top'"
              :hideAfter="0"
            ></CustomTooltip>
          </div>
          <div class="circle-value">
            <span>{{
              bigNumberTransform(item.valueFormat) ||
              bigNumberTransform(item.value)
            }}</span>
            <span v-if="item.unit">({{ item.unit }})</span>
            <span v-if="item.percentage" class="ml-16">{{
              item.percentage
            }}</span>
          </div>
        </div>
      </div>
    </div>
    <div
      v-if="otherType == 'one'"
      class="custom-circle-legend-one"
      :class="getLegendClass"
      :style="getLegendStyle"
    >
      <div
        class="custom-circle-legend-item custom-circle-legend-item-center"
        @mouseover="handleHover(item.name)"
        @mouseleave="handleHoverLeave(item.name)"
        :class="activeList.includes(item.name) ? 'is-active' : 'is-unactive'"
        v-for="(item, index) in chartData"
        @click="handleClick(item.name)"
      >
        <div
          class="circle-icon"
          :style="{
            background: activeList.includes(item.name)
              ? colorBg[index]
              : '#ddd',
          }"
        ></div>
        <div class="circle-icon-flex">
          <div class="legend-label ya-primary-text" :class="getLabelWidth">
            <CustomTooltip
              :show="true"
              :text="item.name"
              :placement="'top'"
              :hideAfter="0"
            ></CustomTooltip>
          </div>
          <div class="legend-value ya-regular-text">
            {{ item.valueFormat || item.value }}{{ item.unit }}
          </div>
        </div>
      </div>
    </div>
    <div
      v-if="otherType == 'three'"
      class="custom-circle-legend-one"
      :class="getLegendClass"
      :style="getLegendStyle"
    >
      <div
        class="three-lengend-item custom-circle-legend-item-center"
        @mouseover="handleHover(item.name)"
        @mouseleave="handleHoverLeave(item.name)"
        :class="activeList.includes(item.name) ? 'is-active' : 'is-unactive'"
        v-for="(item, index) in chartData"
        @click="handleClick(item.name)"
      >
        <div
          class="circle-icon"
          :style="{
            background: activeList.includes(item.name)
              ? colorBg[index]
              : '#ddd',
          }"
        ></div>
        <div class="circle-icon-flex flex-one">
          <div class="legend-label ya-primary-text" :class="getLabelWidth">
            {{ item.name }}
          </div>
          <div class="legend-label-flex-bt">
            <div class="legend-value">
              {{
                bigNumberTransform(item.valueFormat) ||
                bigNumberTransform(item.value)
              }}{{ item.unit }}
            </div>
            <div class="legend-value">
              {{ item.percentage }}
            </div>
          </div>
        </div>
      </div>
    </div>
    <div
      v-if="otherType == 'four'"
      class="custom-circle-legend-four"
      :class="getLegendClass"
      :style="getLegendStyle"
    >
      <div
        class="custom-circle-legend-item custom-circle-legend-item-center custom-circle-legend-item-four"
        @mouseover="handleHover(item.name)"
        @mouseleave="handleHoverLeave(item.name)"
        :class="activeList.includes(item.name) ? 'is-active' : 'is-unactive'"
        v-for="(item, index) in chartData"
        @click="handleClick(item.name)"
      >
        <div
          class="circle-icon circle-icon-four"
          :style="{
            background: activeList.includes(item.name)
              ? colorBg[index]
              : '#ddd',
            border: activeList.includes(item.name)
              ? item.borderColor
              : '1px solid #ddd',
          }"
        ></div>
        <div class="circle-icon-flex">
          <div class="legend-four-label" :class="getLabelWidth">
            <CustomTooltip
              :show="true"
              :text="item.name"
              :placement="'top'"
              :hideAfter="0"
            ></CustomTooltip>
          </div>
          <div class="legend-four-img">
            <img src="../../../assets/image/screen/level-bg.png" alt="" />
          </div>
          <div
            class="legend-four-value-legend"
            :style="{ color: activeList.includes(item.name) ? '' : '#ddd' }"
          >
            <div class="legend-four-value">
              {{
                bigNumberTransform(item.valueFormat) ||
                bigNumberTransform(item.value)
              }}
            </div>
            <div>{{ item.unit }}</div>
          </div>
        </div>
      </div>
    </div>
  </div>
  <div class="chart-type" v-if="otherType == 'five'">
    <div
      class="chart"
      ref="chartRef"
      :style="{ width: '100%', height: '100%' }"
    ></div>
    <div v-if="showLabel">
      <div :class="getLegendClass" :style="getLegendStyle">
        <div
          class="cir-label"
          @mouseover="handleHover(item.name)"
          @mouseleave="handleHoverLeave(item.name)"
          :class="activeList.includes(item.name) ? 'is-active' : 'is-unactive'"
          v-for="(item, index) in chartData"
          @click="handleClick(item.name)"
        >
          <div
            class="cir-icon"
            :style="{
              background: activeList.includes(item.name)
                ? colorBg[index]
                : '#ddd',
            }"
          ></div>
          <div :class="getLabelWidth">
            {{ item.name }}
          </div>
          <div class="cir-value">
            {{ bigNumberTransform(item.value) }}
            <span class="cir-per" v-if="item.percentage"
              >({{ item.percentage }})</span
            >
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style lang="scss">
.chart-flex {
  position: relative;
  display: flex;
  align-items: center;
  width: 100%;
  height: 100%;
}
.chart-type {
  width: 100%;
  height: 100%;
}
.custom-circle-legend {
  position: absolute;
  width: 50%;
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  max-height: 100%;
  overflow: auto;
}

.custom-circle-legend-item {
  display: flex;
  width: 48%;
  margin-bottom: 12px;
  // margin-right: 2%;
  cursor: pointer;

  .circle-icon-flex {
    display: flex;
    align-items: center;
    // justify-content: space-between;
    width: 94%;
  }

  .circle-icon {
    width: 10px;
    height: 10px;
    border-radius: 10px;
    flex-shrink: 0;
    margin-right: 5px;
    background: #ddd;
    position: relative;
    top: 5px;
  }

  .legend-label {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    -o-text-overflow: ellipsis;
    font-size: 12px;
    color: rgba(0, 0, 0, 0.65);
    flex: 1;
    padding-right: 8px;
    min-width: 60px;
    // padding: 0 20px 0 0;
    // width: 50%;
    // margin-right: 20px;
  }

  .width-self {
    min-width: 0;
  }

  .legend-value {
    font-size: 14px;
    font-weight: 400;
    color: #819ba5;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    // min-width: 40%;
    text-align: right;
    max-width: 80%;
    // min-width: 120px;
    // margin-left: 30px;
  }
}
.legend-label-flex-bt {
  display: flex;
}
.flex-one {
  flex: 1;
}
.chart-flex .custom-circle-legend-item:last-child {
  margin-bottom: 0;
}
.custom-circle-legend-item-center {
  width: 100%;
}

.custom-circle-legend-item.is-active {
  .legend-label {
    color: rgba(0, 0, 0, 0.65);
  }

  .legend-value {
    color: rgba(0, 0, 0, 0.4);
  }
}

.custom-circle-legend-item.is-unactive {
  .circle-icon {
    background: #ddd;
  }

  .legend-label {
    color: #ddd;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    -o-text-overflow: ellipsis;
  }

  .legend-value {
    color: #ddd;
  }
}

.custom-circle-legend.legend-vertical {
  display: flex;
  flex-direction: column;
}

.custom-circle-legend-one {
  position: absolute;
  width: 50%;
}
.custom-circle-legend-four {
  width: 50%;
}
.three-lengend-item {
  display: flex;
  margin-bottom: 10px;
  cursor: pointer;
  .circle-icon {
    width: 10px;
    height: 10px;
    border-radius: 6px;
    flex-shrink: 0;
    margin-right: 5px;
    background: #ddd;
    position: relative;
    top: 5px;
  }
  .three-circle-icon-flex {
    width: 100%;
  }
  .legend-label {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    -o-text-overflow: ellipsis;
    font-size: 14px;
    color: rgba(0, 0, 0, 0.65);
    width: 100%;
  }
  .legend-value {
    font-size: 14px;
    color: #819ba5;
    margin-top: 2px;
    width: 120px;
  }
}
.custom-circle-legend-one .three-lengend-item:last-child {
  margin-bottom: 0;
}
.ml-16 {
  margin-left: 16px;
}
.legend-four-label {
  color: #fff !important;
  font-size: 12px;
  font-size: 16px;
}
.legend-four-img {
  position: relative;
  top: 2px;
  margin-left: 22px;
  margin-right: 22px;
}
.legend-four-value-legend {
  flex: 1;
  display: flex;
  align-items: center;
  color: #ffffff;
}
.legend-four-value {
  text-align: left;
  font-size: 16px;
  color: #ffffff;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  text-align: right;
  max-width: 100%;
  font-family: YouSheBiaoTiHei;
}
.circle-icon-four {
  border-radius: 0 !important;
  width: 6px !important;
  height: 6px !important;
  top: 1px !important;
}
.custom-circle-legend-item-four {
  align-items: center;
  margin-bottom: 28px !important;
}
.custom-circle-legend-item-four:last-child {
  margin-bottom: 0 !important;
}

.rose-linechart-tooltip-black {
  background: rgba(22, 43, 97, 0.92);
  box-shadow: 0px 0px 16px 0px rgba(156, 152, 152, 0.2),
    inset 0px 0px 4px 0px rgba(84, 229, 252, 0.65);
  border-radius: 2px;
  color: #fff;
  font-size: 12px;
  padding: 12px;
  font-weight: 400;
  min-width: 100px;
  .rose-linechart-tooltip-item {
    display: flex;
    align-items: center;
  }
  .rose-linechart-tooltip-content-item-icon {
    width: 8px;
    height: 8px;
    border-radius: 50%;
  }
  .rose-linechart-tooltip-content-item-info {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex: 1;
  }
  .rose-linechart-tooltip-content-item-value {
    color: #bac8da;
    margin-left: 20px;
  }
}
.circle-value {
  font-size: 12px;
  color: rgba(23, 70, 89, 0.55);
}

.cir-label {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 16px;
  color: #174659;
  cursor: pointer;
  .cir-icon {
    border-radius: 50%;
    width: 8px;
    height: 8px;
    margin-right: 4px;
  }
  .cir-value {
    margin-left: 30px;
  }
}
.jstcontent {
  justify-content: center;
}
</style>
