<template>
  <div id="echarts" ref="chartRef" :style="echartsStyle" />
</template>

<script setup lang="ts" name="ECharts">
  import {
    ref,
    onMounted,
    onBeforeUnmount,
    watch,
    computed,
    markRaw,
    nextTick,
    onActivated,
  } from 'vue';
  import { EChartsType, ECElementEvent } from 'echarts/core';
  import echarts, { ECOption } from './config';
  import { useDebounceFn } from '@vueuse/core';
  import { useGlobalStore } from '@/stores/modules/global';
  import { storeToRefs } from 'pinia';

  interface Props {
    option: ECOption;
    renderer?: 'canvas' | 'svg';
    resize?: boolean;
    theme?: Object | string;
    width?: number | string;
    height?: number | string;
    onClick?: (event: ECElementEvent) => any;
  }

  const props = withDefaults(defineProps<Props>(), {
    renderer: 'canvas',
    resize: true,
  });

  const echartsStyle = computed(() => {
    return props.width || props.height
      ? { height: props.height + 'px', width: props.width + 'px' }
      : { height: '100%', width: '100%' };
  });

  const chartRef = ref<HTMLDivElement | HTMLCanvasElement>();
  const chartInstance = ref<EChartsType>();

  const draw = () => {
    if (chartInstance.value) {
      chartInstance.value.setOption(props.option);
    }
  };

  watch(props, () => {
    draw();
  });

  const handleClick = (event: ECElementEvent) => props.onClick && props.onClick(event);

  const init = () => {
    if (!chartRef.value) return;
    chartInstance.value = echarts.getInstanceByDom(chartRef.value);

    if (!chartInstance.value) {
      chartInstance.value = markRaw(
        echarts.init(chartRef.value, props.theme, {
          renderer: props.renderer,
        })
      );
      chartInstance.value.on('click', handleClick);
      draw();
    }
  };

  const resize = () => {
    if (chartInstance.value && props.resize) {
      chartInstance.value.resize({ animation: { duration: 300 } });
    }
  };

  const debouncedResize = useDebounceFn(resize, 300, { maxWait: 800 });

  const globalStore = useGlobalStore();
  const { maximize, isCollapse, tabs, footer } = storeToRefs(globalStore);

  watch(
    () => [maximize, isCollapse, tabs, footer],
    () => {
      debouncedResize();
    },
    { deep: true }
  );

  onMounted(() => {
    nextTick(() => init());
    window.addEventListener('resize', debouncedResize);
  });

  onActivated(() => {
    if (chartInstance.value) {
      chartInstance.value.resize();
    }
  });

  onBeforeUnmount(() => {
    chartInstance.value?.dispose();
    window.removeEventListener('resize', debouncedResize);
  });

  defineExpose({
    getInstance: () => chartInstance.value,
    resize,
    draw,
  });
</script>
