import { onBeforeUnmount, onMounted, ref, watch } from "vue";
import { cloneDeep } from "lodash-es";

export default function useChart(ChartClass, props) {
  const chart = ref(null); // 表格实例
  const chartOptions = ref(null); // 图表配置
  const container = ref(null); // 渲染图表元素
  const { onReady, onEvent } = props.config;

  // 全局事件侦听器
  let handler;

  onMounted(() => {
    chartOptions.value = cloneDeep(props.config);

    // 实例化图表
    const chartInstance = new ChartClass(container.value, { ...props.config });
    chartInstance.toDataURL = (type, encoderOptions) => {
      return toDataURL(type, encoderOptions);
    };
    chartInstance.downloadImage = (name, type, encoderOptions) => {
      return downloadImage(name, type, encoderOptions);
    };
    chartInstance.render(); // 渲染图表

    chart.value = chartInstance;

    // 图表渲染完成回调
    if (onReady) {
      onReady(chartInstance);
    }
    // 侦听全局事件
    handler = (event) => {
      if (onEvent) {
        onEvent(chartInstance, event);
      }
    };
    chartInstance.on("*", handler);
  });

  onBeforeUnmount(() => {
    chart.value.destroy();
    chart.value.off("*", handler);
    chart.value = undefined;
  });

  // 配置更改时更新图表
  watch(
    () => props.config,
    (config) => {
      const newConfig = cloneDeep(config);
      chartOptions.value = newConfig;
      chart.value.update(newConfig);
    },
    {
      deep: true,
    }
  );

  const toDataURL = (type = "image/png", encoderOptions) => {
    return chart.value?.chart.canvas.cfg.el.toDataURL(type, encoderOptions);
  };

  const downloadImage = (
    name = "download",
    type = "image/png",
    encoderOptions
  ) => {
    let imageName = name;
    if (name.indexOf(".") === -1) {
      imageName = `${name}.${type.split("/")[1]}`;
    }
    const base64 = chart.value?.chart.canvas.cfg.el.toDataURL(
      type,
      encoderOptions
    );
    let a = document.createElement("a");
    a.href = base64;
    a.download = imageName;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    a = null;
    return imageName;
  };

  return {
    chart,
    container,
  };
}
