<template>
  <div ref="chartRef" style="width: 100%; height: 100%"></div>
</template>
<script>
import { ref, reactive, watchEffect } from 'vue';
import { cloneDeep } from 'lodash';
import { useEcharts } from '@/hooks/useEcharts';
export default {
  name: 'CustomEchartHyalineCake',
  props: {
    chartData: {
      type: Array,
      default: () => [
        {
          name: '项目一',
          value: 60,
        },
        {
          name: '项目二',
          value: 44,
        },
        {
          name: '项目三',
          value: 32,
        },
      ],
    },
    option: {
      type: Object,
      default: () => ({
        k: 1,
        opacity: '0,6',
        itemGap: 0.2,
        itemHeight: 120,
        autoItemHeight: 0,
        legendSuffix: '',
      }),
    },
    type: {
      type: String,
      default: 'bar',
    },
    width: {
      type: String,
      default: '100%',
    },
    height: {
      type: String,
      default: 'calc(100vh - 78px)',
    },
    isSeries: {
      type: Boolean,
      default: false,
    },
  },
  emits: ['click'],
  setup(props, { emit }) {
    const chartRef = ref(null);
    const { setOptions, getInstance, startAutoPlay } = useEcharts(chartRef);
    const option = ref({});
    watchEffect(() => {
      props.chartData && initCharts();
    });

    function initCharts() {
      if (props.option) {
        option.value = Object.assign(option, cloneDeep(props.option));
      }
      option.value = getPie3D(props.chartData, props.option.opacity);
      setOptions(option.value);
    }

    function getParametricEquation(startRatio, endRatio, isSelected, isHovered, k, h) {
      const midRatio = (startRatio + endRatio) / 2;
      const startRadian = startRatio * Math.PI * 2;
      const endRadian = endRatio * Math.PI * 2;
      const midRadian = midRatio * Math.PI * 2;
      if (startRatio === 0 && endRatio === 1) {
        isSelected = false;
      }
      k = typeof k !== 'undefined' ? k : 1 / 3;
      const offsetX = Math.cos(midRadian) * props.option.itemGap;
      const offsetY = Math.sin(midRadian) * props.option.itemGap;
      const hoverRate = 1;
      return {
        u: {
          min: -Math.PI,
          max: Math.PI * 3,
          step: Math.PI / 32,
        },
        v: {
          min: 0,
          max: Math.PI * 2,
          step: Math.PI / 20,
        },

        x(u, v) {
          if (u < startRadian) {
            return offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
          }
          if (u > endRadian) {
            return offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
          }
          return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate;
        },
        y(u, v) {
          if (u < startRadian) {
            return offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
          }
          if (u > endRadian) {
            return offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
          }
          return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate;
        },
        z(u, v) {
          if (u < -Math.PI * 0.5) {
            return Math.sin(u);
          }
          if (u > Math.PI * 2.5) {
            return Math.sin(u) * h * 0.1;
          }
          return Math.sin(v) > 0 ? 1 * h * 0.1 : -1;
        },
      };
    }
    // 生成模拟 3D 饼图的配置项
    function getPie3D(pieData) {
      const series = [];
      // 总和
      let sumValue = 0;
      let startValue = 0;
      let endValue = 0;
      const legendData = [];
      const k = props.option.k ?? 1;
      for (let i = 0; i < pieData.length; i += 1) {
        sumValue += pieData[i].value;

        const seriesItem = {
          name: typeof pieData[i].name === 'undefined' ? `series${i}` : pieData[i].name,
          type: 'surface',
          parametric: true,
          wireframe: {
            show: false,
          },
          pieData: pieData[i],

          itemStyle: {
            // color: colors[i], // 自定义颜色
            opacity: props.option.opacity,
            borderRadius: 300,
            borderColor: '#fff',
            borderWidth: 0,
          },
          pieStatus: {
            selected: false,
            hovered: false,
            k,
          },
        };
        if (typeof pieData[i].itemStyle !== 'undefined') {
          const { itemStyle } = pieData[i];
          typeof pieData[i].itemStyle.color !== 'undefined' ? (itemStyle.color = pieData[i].itemStyle.color) : null;
          typeof pieData[i].itemStyle.opacity !== 'undefined' ? (itemStyle.opacity = pieData[i].itemStyle.opacity) : null;
          seriesItem.itemStyle = itemStyle;
        }
        series.push(seriesItem);
      }
      for (let i = 0; i < series.length; i += 1) {
        endValue = startValue + series[i].pieData.value;
        series[i].pieData.startRatio = startValue / sumValue;
        series[i].pieData.endRatio = endValue / sumValue;
        series[i].parametricEquation = getParametricEquation(
          series[i].pieData.startRatio,
          series[i].pieData.endRatio,
          false,
          false,
          k,
          props.option.autoItemHeight > 0 ? props.option.autoItemHeight * series[i].pieData.value : props.option.itemHeight
        );
        startValue = endValue;
        legendData.push(series[i].name);
      }
      const option = Object.assign(
        {
          tooltip: {
            // tooltip样式调整添加这个类名
            className: 'custom-tooltip-container', // 自定义父容器类名
            backgroundColor: 'rgba(0,0,0,0.5)',
            borderColor: '#35d0c0',
            color: '#fff',
            position: function (point, params, dom, rect, size) {
              var x = point[0];
              var y = point[1];
              var viewWidth = size.viewSize[0];
              var viewHeight = size.viewSize[1];
              var boxWidth = size.contentSize[0];
              var boxHeight = size.contentSize[1];
              // 判断 tooltip 位置，调整其位置使其不会超出图表边界
              if (x + boxWidth > viewWidth) {
                x = x - boxWidth;
              }
              if (y + boxHeight > viewHeight) {
                y = y - boxHeight;
              }
              // 保证 tooltip 始终在图表内部
              if (x < 0) {
                x = 0;
              }
              if (y < 0) {
                y = 0;
              }

              return [x, y];
            },
            formatter: (params) => {
              if (params.seriesName !== 'mouseoutSeries') {
                return `
                <span style="color:#FFF">
                  ${params.seriesName}<br/>
                    <span style="display:inline-block;
                    margin-right:5px;
                    border-radius:10px;
                    width:10px;
                    height:10px;
                    background-color:${params.color};"></span>
                    ${option.series[params.seriesIndex].pieData.value}
                  </span>
                  `;
              }
              return '';
            },
          },
          xAxis3D: {
            min: -1,
            max: 1,
          },
          yAxis3D: {
            min: -1,
            max: 1,
          },
          zAxis3D: {
            min: -1,
            max: 1,
          },
          grid3D: {
            show: false,
            boxHeight: 5,
            top: '0',
            left: '-20%',
            viewControl: {
              //3d效果可以放大、旋转等，请自己去查看官方配置
              alpha: 60, //角度(这个很重要 调节角度的)
              distance: 240, //调整视角到主体的距离，类似调整zoom(这是整体大小)
              rotateSensitivity: 10, //设置旋转灵敏度，为0无法旋转
              zoomSensitivity: 10, //设置缩放灵敏度，为0无法缩放
              panSensitivity: 10, //设置平移灵敏度，0无法平移
              autoRotate: true, //自动旋转
              autoRotateAfterStill: 2, //在鼠标静止操作后恢复自动旋转的时间间隔,在开启 autoRotate 后有效
            },
          },
          legend: {
            show: true,
            left: '50%', // 将图例放在图表右侧
            top: 'center', // 垂直居中
            orient: 'vertical',
            icon: 'circle',
            itemHeight: 12,
            itemWidth: 12,
            itemGap: 10,
            textStyle: {
              color: '#fff',
              fontSize: 14,
              fontWeight: '400',
            },
            formatter: (name) => {
              if (props.chartData.length) {
                const item = props.chartData.filter((item) => item.name === name)[0];
                return `${name}`;
              }
            },
          },
          series,
        },
        props.option
      );
      return option;
    }
    function onClick(params) {
      emit('click', params);
    }
    return { chartRef };
  },
};
</script>
