<template>
  <custom-echart-pie-3d :chart-data="state.data" height="100%" :option="state.option" />
</template>
<script setup>
import { reactive, watch } from 'vue';
import { isEmpty } from '@/utils';

const props = defineProps({
  data: {
    type: Array,
    default: () => [],
  },
});

const state = reactive({
  option: {},
  data: [],
  text: '',
});

function getParametricEquation(startRatio, endRatio, isSelected, isHovered, k, h) {
  // 计算
  let midRatio = (startRatio + endRatio) / 2;
  let startRadian = startRatio * Math.PI * 2;
  let endRadian = endRatio * Math.PI * 2;
  let midRadian = midRatio * Math.PI * 2;
  // 如果只有一个扇形，则不实现选中效果。
  if (startRatio === 0 && endRatio === 1) {
    isSelected = false;
  }
  // 通过扇形内径/外径的值，换算出辅助参数 k（默认值 1/3）
  k = typeof k !== 'undefined' ? k : 1 / 3;
  // 计算选中效果分别在 x 轴、y 轴方向上的位移（未选中，则位移均为 0）
  let offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0;
  let offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0;
  // 计算高亮效果的放大比例（未高亮，则比例为 1）
  let hoverRate = isHovered ? 1.05 : 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: function (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: function (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: function (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;
    },
  };
}

function fomatFloat(num, n) {
  var f = parseFloat(num);
  if (isNaN(f)) {
    return false;
  }
  f = Math.round(num * Math.pow(10, n)) / Math.pow(10, n); // n 幂
  var s = f.toString();
  var rs = s.indexOf('.');
  if (rs < 0) {
    rs = s.length;
    s += '.';
  }
  while (s.length <= rs + n) {
    s += '0';
  }
  return s;
}

function getHeight3D(series, height) {
  series.sort((a, b) => {
    return b.pieData.value - a.pieData.value;
  });
  return (height * 20) / series[0].pieData.value;
}

function getPie3D(pieData, internalDiameterRatio) {
  let series = [];
  let sumValue = 0;
  let startValue = 0;
  let endValue = 0;
  let legendData = [];
  let legendBfb = [];
  let k = 1 - internalDiameterRatio;
  pieData.sort((a, b) => {
    return b.value - a.value;
  });
  for (let i = 0; i < pieData.length; i++) {
    sumValue += pieData[i].value;
    let seriesItem = {
      //名称
      name: typeof pieData[i].name === 'undefined' ? `series${i}` : pieData[i].name,
      type: 'surface',
      //是否为参数曲面（是）
      parametric: true,
      //曲面图网格线（否）上面一根一根的
      wireframe: {
        show: false,
      },
      pieData: pieData[i],
      pieStatus: {
        selected: false,
        hovered: false,
        k: k,
      },

      //设置饼图在容器中的位置(目前没发现啥用)
      //   center: ['50%', '100%']
    };

    //曲面的颜色、不透明度等样式。
    if (typeof pieData[i].itemStyle != 'undefined') {
      let itemStyle = {};
      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);
  }

  legendData = [];
  legendBfb = [];
  for (let i = 0; i < series.length; i++) {
    endValue = startValue + series[i].pieData.value * 1;
    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,
      series[i].pieData.value
    );
    startValue = endValue;
    let bfb = fomatFloat(series[i].pieData.value / sumValue, 4);
    legendData.push({
      name: series[i].name,
      value: bfb,
    });
    legendBfb.push({
      name: series[i].name,
      value: bfb,
    });
  }

  let boxHeight = getHeight3D(series, 15);
  let option = {
    legendSuffix: '%',
    legend: {
      data: legendData,
      // color: ['#8FD7FC', '#466BE7', '#F4BB29', '#49C384', '#8FD7FC', '#466BE7', '#F4BB29', '#49C384'],
      orient: 'vertical',
      right: 10,
      top: 'center',
      itemGap: 20,
      show: true,
      icon: 'rect',
      itemHeight: 16,
      itemWidth: 16,
      textStyle: {
        fontSize: 14,
        color: '#B8DDFF',
        lineHeight: 20,
      },
      formatter: (name) => {
        if (state.data.length) {
          const item = state.data.filter((item) => item.name === name)[0];
          console.log(item);
          return `${name} ${item.pieData.value}${state.option.legendSuffix ?? ''}` + `\n` + `${item.pieData.quantity}家`;
        }
      },
    },
    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.quantity}家
                  </span>
                  `;
        }
        return '';
      },
    },
    xAxis3D: {
      min: -1,
      max: 1,
    },
    yAxis3D: {
      min: -1,
      max: 1,
    },
    zAxis3D: {
      min: -1,
      max: 1,
    },
    grid3D: {
      show: false,
      boxHeight: boxHeight,
      left: '-20%',
      top: -20,
      viewControl: {
        alpha: 30, //角度(这个很重要 调节角度的)
        distance: 150, //调整视角到主体的距离，类似调整zoom(这是整体大小)
        rotateSensitivity: 1, //设置为0无法旋转
        zoomSensitivity: 0, //设置为0无法缩放
        panSensitivity: 0, //设置为0无法平移
        autoRotate: true, //自动旋转
      },
    },
    series: series,
  };
  return option;
}

const initData = (pieData = []) => {
  const option = getPie3D(pieData, 0.8);
  state.option = option;
  state.data = option.series;
};

watch(
  () => props.data,
  (val) => {
    if (!isEmpty(val)) {
      const pieData = val.map((row) => {
        return {
          name: row.name,
          value: row.value,
          quantity: row.quantity,
        };
      });
      initData(pieData);
    }
  },
  {
    deep: true,
    immediate: true,
  }
);
</script>
