import { nextTick, onBeforeUnmount, onMounted, watch } from 'vue'
import { init } from 'echarts/core'

export function useEcharts(chartElement, chartOptions) {
  let chartInstance = null
  let resizeObserver = null
  let renderFrame = 0

  function renderChart() {
    if (!chartElement.value) {
      return
    }
    if (!chartInstance) {
      chartInstance = init(chartElement.value, null, { renderer: 'canvas' })
      chartInstance.resize()
    }
    chartInstance.setOption(chartOptions.value, true)
  }

  function handleResize() {
    chartInstance?.resize()
  }

  function scheduleRender() {
    if (typeof window === 'undefined') {
      renderChart()
      return
    }
    if (renderFrame) {
      window.cancelAnimationFrame(renderFrame)
    }
    renderFrame = window.requestAnimationFrame(() => {
      renderFrame = 0
      renderChart()
    })
  }

  function bindResize() {
    if (!chartElement.value) {
      return
    }
    if (typeof ResizeObserver !== 'undefined') {
      resizeObserver = new ResizeObserver(handleResize)
      resizeObserver.observe(chartElement.value)
    }
    window.addEventListener('resize', handleResize)
  }

  function unbindResize() {
    resizeObserver?.disconnect()
    resizeObserver = null
    window.removeEventListener('resize', handleResize)
  }

  onMounted(() => {
    renderChart()
    bindResize()
  })

  onBeforeUnmount(() => {
    unbindResize()
    if (renderFrame && typeof window !== 'undefined') {
      window.cancelAnimationFrame(renderFrame)
      renderFrame = 0
    }
    if (chartInstance) {
      chartInstance.dispose()
      chartInstance = null
    }
  })

  watch(chartOptions, () => {
    nextTick(scheduleRender)
  }, { deep: true })

  return {
    renderChart
  }
}
