<template>
  <section class="AiEchart">
    <div ref="AiEchart" class="chart" :style="{minWidth:grid.width,minHeight:grid.height}"/>
    <slot v-if="$slots.default"/>
    <render-component v-else-if="ops.render" :render="ops.render" :options="chartOptions" :data="data"/>
  </section>
</template>

<script>
import * as echarts from 'echarts'

export default {
  name: "AiEchart",
  props: {
    data: {default: () => []},
    ops: {default: () => ({})},
    type: {default: "line"},
    series: Object,
    theme: {
      default: '0'
    }
  },
  components: {
    renderComponent: {
      functional: true,
      props: {
        render: Function,
        options: {default: () => ({})},
        data: {default: () => []}
      },
      render(h, ins) {
        let {options = {}, data} = ins.props
        return ins.props.render(h, {...options, data})
      }
    }
  },

  data() {
    return {
      chart: null,
      timer: null
    }
  },
  computed: {
    colors () {
      if (this.theme === '0') {
        return ['#2896FF', '#09DBFE', '#61FDB9', '#FFBB69', '#8429FF', '#ea7ccc']
      }

      return ['#D4380D', '#CF1322', '#D55800', '#FA8C16', '#FFC53D', '#FFA940', '#FFC53D', '#780000']
    },

    chartOptions() {
      let {type, data, ops: options = {}} = this,
          style = this.series ? this.series : this.ops.daemon ? this.ops.daemon : {},
          colors = this.theme === '1' ? this.colors : (options.color || this.colors),
          legend = {textStyle: {color: '#fff', padding: [0, 0, 0, 8], fontSize: 14}},
          series = data?.[0] ? Array(Object.keys(data?.[0]).length - 1).fill(1)
          .map((e, i) => ({type, ...(typeof style == 'object' ? style : style(colors[i]))})) : []
      let ops = {
        tooltip: {},
        xAxis: {
          type: 'category', nameGap: 20, axisTick: false,
          axisLabel: {
            color: '#fff',
            interval: 0,
            rotate: this.data.length > 10 ? 40 : 0
          },
          axisLine: {
            lineStyle: {
              color: this.theme === '1' ? 'rgba(239, 163, 51, 0.8)' : 'rgba(255,255,255,.5)'
            }
          }
        },
        // 声明一个 Y 轴，数值轴。
        yAxis: {
          nameGap: 23, minInterval: 1,
          splitLine: {
            lineStyle: {
              color: this.theme === '1' ? 'rgba(255, 197, 52, 0.4)' : 'rgba(255, 255, 255, .2)',
              type: 'dashed'
            }
          },
          axisLabel: {color: '#fff'}
        },
        legend, series, ...options,
        color: colors,
        grid: {
          left: '0%',
          right: '0%',
          bottom: '0%',
          top: '40px',
          containLabel: true
        },
      }
      if (JSON.stringify(this.ops) != JSON.stringify(ops)) this.$emit("update:ops", ops)
      return ops
    },
    grid() {
      let {width, height} = this.chartOptions.grid || {}
      return {
        width: width ? width + 'px' : 'auto',
        height: height ? height + 'px' : 'auto'
      }
    }
  },
  watch: {
    data: {
      deep: true, handler(v, old) {
        let oldDims = Object.keys(old?.[0] || {})?.toString(),
            current = Object.keys(v?.[0] || {})?.toString()
        this.getChartData(oldDims != current)
      }
    },

    theme () {
      this.refresh()
    }
  },
  methods: {
    getChartData(render) {
      if (!render) {
        this.chart?.setOption({
          dataset: {
            source: this.data || []
          }
        })
      } else {
        this.chart?.setOption({
          ...this.chartOptions,
          dataset: {
            source: this.data || []
          }
        }, true)
      }
    },
    initChart() {
      this.chart = echarts.init(this.$refs.AiEchart)
      this.chart.setOption(this.chartOptions || {})
    },
    watchResize() {
      this.timer && clearInterval(this.timer)
      this.timer = setInterval(() => {
        if (this.chart?.getHeight() != this.$refs.AiEchart?.clientHeight ||
            this.chart?.getWidth() != this.$refs.AiEchart?.clientWidth) {
          this.chart?.resize()
        }
      }, 1000)
      //5分钟后停止监听
      setTimeout(() => this.timer && clearInterval(this.timer), 5 * 60 * 1000)
    },
    refresh() {
      this.chart.setOption(this.chartOptions || {})
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.watchResize()
      this.initChart()
      this.getChartData()
    })
  },
  beforeDestroy() {
    this.timer && clearInterval(this.timer)
  }
}
</script>

<style lang="scss" scoped>
.AiEchart {
  width: 100%;
  height: 100%;
  flex: 1;
  min-width: 100px;
  min-height: 0;
  position: relative;

  .chart {
    height: 100%;
    min-height: 100px;
  }
}
</style>
