<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: "AiEchartV2",
  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,
      AiEchart: `AiEchart-${new Date().getTime()}`
    }
  },
  computed: {
    colors() {
      if (this.theme === '0') {
        return ['#00F9FF', '#1890FF', '#B13BFF', '#FC3BFF', '#95FF44', '#ea7ccc']
      }

      return ['#FFBA44', '#EC6666', '#FF3E18', '#C9FF82', '#29D7FA', '#ea7ccc']
    },

    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}, show: false},
          series = data?.[0] ? Array(Object.keys(data?.[0]).length - 1).fill(1)
          .map((e, i) => ({type, ...(typeof style == 'object' ? style : style(colors[i]))})) : []
      return {
        tooltip: {},
        xAxis: {
          type: 'category', nameGap: 20, axisTick: false,
          axisLabel: {
            color: '#C3C4C4',
            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)',
              width: 1
            }
          }
        },
        // 声明一个 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: '#C3C4C4'},
          axisLine: {
            lineStyle: {
              color: '#C3C4C4'
            }
          }
        },
        grid: {
          left: '0%',
          right: '0%',
          bottom: '0%',
          top: '26px',
          containLabel: true
        },
        legend, series, ...options,
        color: colors
      }
    },
    grid() {
      let {width, height} = this.chartOptions.grid || {}
      return {
        width: width ? (width - this.legend === '1' ? 160 : 0) + '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: {
    deepAssign() {
      let name, options, src, copy
      let length = arguments.length
      // 记录要复制的对象的下标
      let i = 1
      // target默认是第一个参数
      let target = arguments[0] || {}
      // 如果target不是对象，我们是无法进行复制的，所以设为{}
      if (typeof target !== 'object') {
        target = {}
      }
      // 循环遍历要复制的对象
      for (; i < length; i++) {
        // 获取当前对象
        options = arguments[i]
        // 要求不能为空 避免extend(a,,b)这种情况
        if (options != null) {
          for (name in options) {
            // 目标属性值
            src = target[name]
            // 要复制的对象的属性值
            copy = options[name]

            if (copy && typeof copy == 'object') {
              // 递归调用
              target[name] = this.deepAssign( src, copy)
            } else if (copy !== undefined) {
              target[name] = copy
            }
          }
        }
      }

      return target
    },
    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[this.AiEchart])
      this.chart.setOption(this.chartOptions || {})
    },
    watchResize() {
      this.timer && clearInterval(this.timer)
      this.timer = setInterval(() => {
        if (this.chart?.getHeight() != this.$refs[this.AiEchart]?.clientHeight ||
            this.chart?.getWidth() != this.$refs[this.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 {
  display: flex;
  width: 100%;
  height: 100%;
  flex: 1;
  min-width: 100px;
  min-height: 0;
  position: relative;

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