<!--
 * @Author: changjun
 * @FilePath: /yuan-qingdao-zld-browser/src/components/chart/RoseChart/RoseChart.vue
 * @Date: 2022-09-01 14:25:35
 * @Description: 
 * @LastEditTime: 2022-09-14 14:58:29
 * @LastEditors: changjun
-->
<script setup lang="ts">
import { Ref, defineProps, watchEffect } from "vue";
import type { EChartsOption } from "echarts";
import { useECharts } from "../../../hooks/web/useECharts";
import { colorList, mergeOptions, getCommonTheme, getRoseChartThemeColor } from "../../../components/chart/options/index";
import { isObject } from "../../../utils/is";
const chartRef = ref<HTMLDivElement | null>(null);
const { setOptions, getInstance, echarts } = useECharts(
  chartRef as Ref<HTMLDivElement>
);

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

interface RoseChartProps {
  /**
   * 名称，关联图表的 series
   */
  name: string;
  /**
   * 图表数据
   */
  chartData: any[];
  theme?: string;
  colors?: string[];
  /**
   * 格式化图例显示函数 用于需要显示图例名称之外内容的时候
   */
  legendFormatter?: string | ((name: string) => string);
  labelFormatter?: string | ((name: string) => string);
  /**
   * 是否需要手动设置一些其它的设置，需要结合otherOptions才能起作用
   */
  manual?: boolean;
  pieCenter?: string[];
  radius?: string[];
  /**
   * 手动设置一些其它的设置，需要结合manual才能起作用
   */
  otherOptions?: EChartsOption;
  labelShow?: boolean;
  legendLeft?: string;
  legendRight?: string;
  legendTop?: string;
  labelWidth?: string;
  chartClass?: string;
  legendClass?: string;
  legendShow?: boolean;
}

const {
  name = "",
  chartData = [],
  manual = false,
  otherOptions = {},
  pieCenter = ["50%", "50%"],
  radius = ["10%", "60%"],
  colors = [],
  chartClass = "",
  labelShow = true,
  legendClass = "",
  labelWidth = "default",
  legendLeft = "0",
  legendRight = "0",
  legendTop = "35%",
  legendShow = true,
  theme = 'light',
  labelFormatter = '',
} = defineProps<RoseChartProps>();


const currentTheme = computed(() => {
	return getCommonTheme(unref(theme))
}) as any;

const currentColors = computed(() => {
  if(unref(colors).length > 0) {
    return unref(colors)
  }
  return unref(currentTheme).colorList
}) as any;

const currentRoseChartThemeColor = computed(() => {
  return getRoseChartThemeColor(unref(theme))
}) as any;

let options: EChartsOption = {
  tooltip: {
    show: true,
    backgroundColor: unref(currentTheme).tooltip.backgroundColor,
    textStyle: {
      color: unref(currentTheme).tooltip.textStyle.color,
    },
    borderColor: "transparent",
    extraCssText: "0px 0px 8px 0px rgba(0,0,0,0.2);border-radius: 4px;",
  },

  color: unref(currentColors),


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

  series: [
    {
      name: "",
      type: "pie",
      roseType: "area",
      center: unref(pieCenter),
      radius: unref(radius),
      label: {
        show: unref(labelShow),
        color: unref(currentRoseChartThemeColor).rich.name,
        rich: {
          name: {
            fontSize: 14,
            color: unref(currentRoseChartThemeColor).rich.name,
            padding: [0, 0, 0, 0],
          },
          value: {
            fontSize: 12,
            color: unref(currentRoseChartThemeColor).rich.value,
            padding: [0, 0, 0, 0],
          },
          percent: {
            fontSize: 12,
            color: unref(currentRoseChartThemeColor).rich.percent,
            padding: [0, 0, 0, 10],
          }
        },
      },
      itemStyle: {
        borderRadius: 8,
      },
      showEmptyCircle: true,
      emptyCircleStyle: {
        color: unref(currentRoseChartThemeColor).emptyCircleStyle.color,
      },
      data: chartData,
    },
  ],
};

let activeList = ref([]) as any; // 定义一个激活的状态表
const initChartDataActiveList = () => {
  const list = unref(chartData).map((item) => {
    return item.name;
  });
  activeList.value = list;
};

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

async function initChart() {
  options.series![0].name = unref(name);
  options.series![0].data = unref(chartData);
  options.series![0].center = unref(pieCenter);
  options.series![0].radius = unref(radius);
  options.series![0].label.show = unref(labelShow);
  if(unref(labelFormatter)) {
    options.series![0].label.formatter = unref(labelFormatter);
  }
  options.color = unref(currentColors);
  initChartDataActiveList();
  // 如果是手动设置模式的话
  if (unref(manual) && isObject(unref(otherOptions))) {
    options = mergeOptions(options, unref(otherOptions));
  }
  setOptions(options);
}

onMounted(() => {
  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;
});
</script>
  
  <template>
  <div
    class="chart"
    :class="chartClass"
    ref="chartRef"
    :style="{ width: '100%', height: '100%' }"
  ></div>
  <div
    class="custom-rose-legend"
    v-if="legendShow"
    :class="legendClass"
    :style="getLegendStyle"
  >
    <div
      class="custom-rose-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="legend-label" :class="getLabelWidth">{{ item.name }}</div>
      <div class="legend-value">{{ item.valueFormat || item.value }}</div>
    </div>
  </div>
</template>
  
  
  <style lang="scss">
.custom-rose-legend {
  position: absolute;
  width: 55%;
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;

  .custom-rose-legend-item {
    display: flex;
    align-items: center;
    width: 100%;
    margin-bottom: 12px;
    cursor: pointer;

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

    .legend-label {
      font-size: 12px;
      color: rgba(0, 0, 0, 0.65);
      min-width: 70%;
      max-width: 80%;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

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

    .legend-value {
      font-size: 12px;
      color: rgba(0, 0, 0, 0.4);
      margin-left: 8px;
    }
  }
}

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

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

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

  .legend-label {
    color: #ddd;
  }

  .legend-value {
    color: #ddd;
  }
}
</style>
  