/**
 * @description
 * @param {string} refName 图表容器ref
 * @param {boolean} immediateRender 是否立即渲染图表
 * @param { EchartsMixinOption } options 其他配置项
 *
 * @typedef {Object} EchartsMixinOption
 * @property {Function} beforeInit 图表示例初始化前调用
 * @property {Function} afterInit  图表初始化后调用
 */
export default (refName, immediateRender, options = {}) => {
  const { beforeInit, afterInit } = options
  return {
    props: {
      chartData: {
        type: [Object, Array], // required: true
        default: () => []
      }
    },

    data() {
      return {
        instance: null,
        observer: null,
        reUpdateDate: null
      }
    },

    watch: {
      chartData: {
        handler(value) {
          if (this.instance) {
            this.update && typeof this.update === 'function' && this.update(value)
          } else {
            this.reUpdateDate = value
          }
        },
        immediate: true,
        deep: true
      }
    },

    mounted() {
      this.startObserve()
    },

    methods: {
      startObserve() {
        if (!immediateRender) {
          this.observer = new IntersectionObserver(this.observerCB, { threshold: 0.7 })
          this.observer.observe(this.$refs[refName])
        } else {
          this.init()
        }
      },

      observerCB(e) {
        const { isIntersecting } = e[0]
        if (isIntersecting) {
          this.init()
          this.destroyObserver()
        }
      },

      init() {
        if (this.instance) return
        beforeInit && typeof beforeInit === 'function' && beforeInit(this.$echarts)
        this.instance = this.$echarts.init(this.$refs[refName], null, { renderer: 'svg' })
        afterInit && typeof afterInit === 'function' && afterInit()
        this.instance.setOption(this.staticOptions)
        this.reUpdateDate && this.update(this.reUpdateDate)
      },

      resize() {
        if (this.instance) {
          this.instance.resize()
        }
      },

      destroyObserver() {
        if (this.observer) {
          this.observer.unobserve(this.$refs[refName])
          this.observer = null
        }
      }
    },

    beforeDestroy() {
      this.destroyObserver()
      this.instance = null
      this.reUpdateDate = null
    }
  }
}
