import type { Ref } from "vue";
import type { EChartsOption } from "echarts";
import * as echarts from "echarts";
import { unref, nextTick, watch, computed, ref } from "vue";
import { tryOnUnmounted, useDebounceFn, useEventListener } from "@vueuse/core";

export function useEcharts(
  elRef: Ref<HTMLElement>,
  theme: "default" | "dark" | "light" = "default"
) {
  let chartInstance: echarts.ECharts | null = null;
  let resizeFn: () => void = resize;
  const cacheOptions = ref({});

  let removeResizeFn: () => void;

  const getOptions = computed(() => {
    return cacheOptions.value;
  });

  resizeFn = useDebounceFn(resize, 200);

  function resize() {
    chartInstance?.resize({
      animation: {
        duration: 300,
        easing: "quadraticIn",
      },
    });
  }

  function initCharts(t = theme) {
    const el = unref(elRef);
    if (!el || !unref(el)) {
      return;
    }

    chartInstance = echarts.init(el, t);
    const removeEvent = useEventListener(window, "resize", resizeFn);

    removeResizeFn = removeEvent;
  }

  function setOptions(options: EChartsOption, clear = true) {
    cacheOptions.value = options;
    return new Promise((resolve) => {
      if (unref(elRef)?.offsetHeight === 0) {
        setTimeout(() => {
          setOptions(unref(getOptions));
          resolve(null);
        }, 30);
      }
      nextTick(() => {
        setTimeout(() => {
          if (!chartInstance) {
            initCharts("default");

            if (!chartInstance) return;
          }
          clear && chartInstance?.clear();

          chartInstance?.setOption(unref(getOptions));
          resolve(null);
        }, 30);
      });
    });
  }

  watch(
    () => theme,
    (theme) => {
      if (chartInstance) {
        chartInstance.dispose();
        initCharts(theme as "default");
        setOptions(cacheOptions.value);
      }
    }
  );

  tryOnUnmounted(() => {
    if (!chartInstance) return;
    removeResizeFn();
    chartInstance.dispose();
    chartInstance = null;
  });

  function getInstance(): echarts.ECharts | null {
    if (!chartInstance) {
      initCharts("default");
    }
    return chartInstance;
  }

  return {
    setOptions,
    resize,
    echarts,
    getInstance,
  };
}
