<!--
 * @Author: changjun
 * @FilePath: /yuan-qingdao-zld-browser/src/components/chart/CircularDiagram/CircularDiagram.vue
 * @Date: 2022-08-27 15:51:36
 * @Description: 
 * @LastEditTime: 2023-08-31 13:40:52
 * @LastEditors: 曹文丽
-->
<script setup lang="ts">
import { Ref, defineProps, watchEffect, reactive, ref, unref, onMounted, computed } from "vue";
import type { EChartsOption } from "echarts";
import { useECharts } from "../../../hooks/web/useECharts";
import { bigNumberTransform } from "../../../utils/utils";
import {
  getThemeColor,
  mergeOptions,
  securityColorList,
  getCommonTheme,
} from "../../../components/chart/options/index";
import { isObject } from "../../../utils/is";
import { mapMapping } from "../../../assets/map/provinceData";
const mapData = reactive(mapMapping());
const colorList = getThemeColor().colorList;
const chartRef = ref<HTMLDivElement | null>(null);
const { setOptions, getInstance, echarts } = useECharts(
  chartRef as Ref<HTMLDivElement>
);
const yaTheme = localStorage.getItem("YA_THEME");

const commonChartTheme = computed(() => {
  return getCommonTheme(unref("light"));
}) as any;

/**
 * @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;
  legendWidth?: string;
  legendTop?: string;
  labelWidth?: string;
  chartClass?: string;
  legendClass?: string;
  legendLayout?: string;
  legendClick?: boolean;
  otherType?: string;
  colorBg?: any[];
  titleText?: string;
  titleSubText?: string;
  chartWidth?: string;
  tooltipFormatter?:
  | string
  | ((params: any, ticket: any, callback: any) => string);
  bigNumberTransformClose?: boolean
}

const {
  name = "",
  chartData = [],
  legendFormatter = (name) => name,
  manual = false,
  otherOptions = {},
  pieCenter = ["25%", "50%"],
  radius = ["50%", "70%"],
  chartClass = "",
  legendClass = "",
  labelWidth = "default",
  legendLeft = "0",
  legendRight = "0",
  legendWidth = "0",
  legendTop = "35%",
  legendLayout = "horizontal",
  legendClick = true,
  otherType = "default",
  colorBg = getThemeColor().colorList,
  titleText = "",
  titleSubText = "",
  tooltipFormatter = "",
  tooltipValueFormatter = (val) => val,
  chartWidth = "50%",
  bigNumberTransformClose = false
} = defineProps<CircularDiagramChartProps>();
let options: EChartsOption = {
  title: {
    text: unref(titleText),
    subtext: unref(titleSubText),
    left: "48%",
    top: "40%",
    x: "center",
    textAlign: "center",
    textStyle: {
      color: yaTheme === "light" ? "rgba(0, 0, 0, 0.4)" : "#96A2B5",
      fontSize: 16,
      align: "center",
    },
    subtextStyle: {
      color: yaTheme === "light" ? "rgba(0, 0, 0, 0.4)" : "#96A2B5",
      fontSize: 32,
      align: "center",
    },
  },

  tooltip: {
    show: true,
    confine: true,
    textStyle: {
      color: unref(commonChartTheme).tooltip.textStyle.color,
    },
    backgroundColor: unref(commonChartTheme).tooltip.backgroundColor,
    borderColor: "transparent",
    extraCssText: "border-radius: 4px;",
    valueFormatter: unref(tooltipValueFormatter),
    formatter: function (params) {
      const { data, color } = params || {};
      const { name, value } = data || {};
      return `
        <div class="yaPie">
          <span style="background-color: ${color};display: inline-block;width: 8px;height: 8px;border-radius: 50%;"></span>
          <span>${name}</span>
          <span style="padding-left: 8px">${value}</span>
        </div>
      `;
    },
  },

  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",
      minAngle: 3,
      center: unref(pieCenter),
      radius: unref(radius),
      label: {
        show: false,
      },
      data: chartData,
      showEmptyCircle: true,
      emptyCircleStyle: {
        color: "#4A6184",
      },
    },
  ],
};

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 = 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);
  }
  initChartDataActiveList();
  setOptions(options);
}

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

watchEffect(() => {
  console.log(chartData, "chartDatachartData");
  initChart();
});

const handleClick = (name) => {
  if (!legendClick) return;
  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);
  }
  if (unref(legendWidth) !== "0") {
    _style.width = unref(legendWidth);
  }
  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">
    <div class="chart" :class="chartClass" ref="chartRef"
      :style="{ width: otherType === 'two' ? '35%' : chartWidth, height: '100%' }"></div>
    <div v-if="otherType == 'default'" class="custom-circle-legend" style="width: 60%" :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" :class="{
            getLabelWidth,
          }">
            {{ item.name }}
          </div>
          <div class="legend-value">
            {{ bigNumberTransformClose ? (item.valueFormat || item.value) : bigNumberTransform(item.valueFormat ||
              item.value)
            }}
            <span v-if="item.radio">{{ item.radio }}</span>
          </div>
        </div>
      </div>
    </div>
    <div v-if="otherType == 'two'" class="custom-circle-legend" style="width: 65%" :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)
            ? colorList[index]
            : '#ddd',
        }"></div>
        <div class="circle-icon-flex">
          <div class="legend-label ya-primary-text" :class="getLabelWidth">
            <CustomTooltip :show="true" :text="item.name"></CustomTooltip>
          </div>
          <div class="legend-value ya-regular-text">
            {{ item.valueFormat || item.value }}%
          </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" :class="getLabelWidth">
            <CustomTooltip :show="true" :text="item.name"></CustomTooltip>
          </div>
          <div class="legend-value">
            {{ bigNumberTransform(item.valueFormat || item.value) }}
          </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">
          <div class="legend-label" :class="getLabelWidth">
            {{ item.name }}
          </div>
          <div class="legend-value">
            {{ item.valueFormat || item.value }}{{ item.unit }}
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style lang="scss">
.yaPie {
  .ya-pie-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
  }
}
</style>
<style lang="scss" scoped>
.chart-flex {
  display: flex;
  align-items: center;
  // justify-content: right;
  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;
  align-items: center;
  width: 44%;
  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: 6px;
    height: 6px;
    border-radius: 6px;
    flex-shrink: 0;
    margin-right: 5px;
    background: #ddd;
  }

  .legend-label {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    -o-text-overflow: ellipsis;
    font-size: 14px;
    color: #8cecff;
    flex: 1;
    padding-right: 8px;
    min-width: 30px;
    // padding: 0 20px 0 0;
    // width: 50%;
    // margin-right: 20px;
  }

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

  .legend-value {
    font-size: 12px;
    color: #8cecff;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-family: YouSheBiaoTiHei;
    // min-width: 40%;
    text-align: right;
    max-width: 80%;
    // min-width: 120px;
    // margin-left: 30px;
  }
}

.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(154, 239, 255, 1);
  }

  .legend-value {
    color: rgba(154, 239, 255, 1);
  }
}

.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 {
  width: 50%;
}

.three-lengend-item {
  display: flex;
  margin-bottom: 23px;
  cursor: pointer;

  .circle-icon {
    width: 6px;
    height: 6px;
    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: 12px;
    color: #9aefff;
    width: 100%;
  }

  .legend-value {
    font-size: 12px;
    color: #5bcbe2;
    margin-top: 2px;
    // font-family: YouSheBiaoTiHei;
  }
}

.custom-circle-legend-one .three-lengend-item:last-child {
  margin-bottom: 0;
}

.rose-linechart-tooltip {

  // background: rgba(9, 103, 138, 0.8);
  // padding: 9px 12px;
  // border-radius: 3px;
  // color: #fff;
  // font-size: 12px;
  // font-weight: 400;
  // min-width: 150px;
  // padding-top: 12px;
  .rose-linechart-tooltip-content-item-icon {
    // margin-top: 12px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
  }

  .rose-linechart-tooltip-subtitle {
    color: #fff;
    font-size: 12px;
    // margin-top: 12px;
  }

  .rose-linechart-tooltip-content-item-value {
    font-weight: 400;
    color: #fff;
  }

  .ya-content {
    display: flex;
  }

  .rose-linechart-tooltip-content {
    padding-left: 20px;
  }
}
</style>
