<!--
  基础图表组件
  封装 ECharts 的基本功能，所有图表组件的父类
-->

<template>
  <div
    ref="chartRef"
    class="base-chart"
    :style="{ height: height, width: '100%' }"
  ></div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, watch, nextTick, computed } from 'vue'
import { useECharts } from '@/composables/useECharts'
import type { EChartOption } from 'echarts'

/** Props */
interface Props {
  option: EChartOption
  height?: string
  autoResize?: boolean
  loading?: boolean
  theme?: string | object
}

const props = withDefaults(defineProps<Props>(), {
  height: '400px',
  autoResize: true,
  loading: false,
  theme: undefined,
})

/** Emits */
interface Emits {
  (e: 'ready', chart: any): void
  (e: 'click', params: any): void
}

const emit = defineEmits<Emits>()

/** 图表容器引用 */
const chartRef = ref<HTMLElement | null>(null)

/** 使用 ECharts Composable */
const { chart, isReady, initChart, setOption, showLoading, hideLoading, resize, dispose, on, off } = useECharts(
  chartRef,
  props.theme
)

/** 监听配置变化 */
watch(
  () => props.option,
  (newOption) => {
    if (isReady.value) {
      setOption(newOption, true)
    }
  },
  { deep: true }
)

/** 监听加载状态 */
watch(
  () => props.loading,
  (loading) => {
    if (loading) {
      showLoading()
    } else {
      hideLoading()
    }
  },
  { immediate: true }
)

/** 监听图表就绪 */
watch(isReady, (ready) => {
  if (ready && chart.value) {
    emit('ready', chart.value)

    // 绑定点击事件
    on('click', (params) => {
      emit('click', params)
    })
  }
})

/** 初始化 */
onMounted(async () => {
  await nextTick()
  if (chartRef.value) {
    initChart()
  }
})

/** 清理 */
onBeforeUnmount(() => {
  dispose()
})

/** 暴露方法 */
defineExpose({
  chart,
  resize,
  refresh: () => setOption(props.option, true),
})
</script>

<style scoped lang="scss">
.base-chart {
  width: 100%;
  min-height: 200px;
}
</style>
