<!-- echarts 图表组件封装 https://github.com/ecomfe/vue-echarts -->
<template>
  <div class="ele-charts"></div>
</template>

<script>
import * as echarts from 'echarts';
import EleCharTheme from './theme.js';
// 改变后需要重新初始化的属性
const INIT_TRIGGERS = ['theme', 'initOptions'];
// 改变后需要重新监听options改变的属性
const REWATCH_TRIGGERS = ['manualUpdate', 'watchShallow'];

export default {
  name: 'EleChart',
  props: {
    // 主题
    theme: {
      type: [String, Object],
      default() {
        return EleCharTheme;
      }
    },
    // 图表初始配置
    initOptions: Object,
    // 图表配置
    options: Object,
    // 实例分组
    group: String,
    // 是否关闭深度监听options改变
    watchShallow: Boolean,
    // 是否关闭响应式更新
    manualUpdate: Boolean
  },
  computed: {
    // 屏幕宽度
    screenWidth() {
      try {
        return this.$store.state.theme.screenWidth;
      } catch (e) {
        return null;
      }
    },
    // 侧边栏折叠状态
    collapse() {
      try {
        return this.$store.state.theme.collapse;
      } catch (e) {
        return null;
      }
    }
  },
  watch: {
    group(group) {
      this.chart.group = group;
    },
    screenWidth() {
      this.resize();
    },
    collapse() {
      setTimeout(() => {
        this.resize();
      }, 360);
    }
  },
  created() {
    this.initOptionsWatcher();
    INIT_TRIGGERS.forEach(prop => {
      this.$watch(
        prop,
        () => {
          this.refresh();
        },
        {deep: true}
      );
    });
    REWATCH_TRIGGERS.forEach(prop => {
      this.$watch(prop, () => {
        this.initOptionsWatcher();
        this.refresh();
      });
    });
  },
  mounted() {
    if (this.options) {
      this.init();
    }
  },
  unmounted() {
    if (this.chart) {
      this.destroy();
    }
  },
  methods: {
    /* 初始化echarts */
    init(options) {
      if (this.chart) {
        return;
      }
      const chart = echarts.init(this.$el, this.theme, this.initOptions);
      if (this.group) {
        chart.group = this.group;
      }
      chart.setOption(options || this.manualOptions || this.options || {}, true);
      // echarts事件监听
      Object.keys(this.$attrs).forEach(event => {
        const handler = this.$attrs[event]
        if (handler instanceof Function) {
          if (event.indexOf('zr:') === 0) {
            chart.getZr().on(event.slice(3), handler);
          } else {
            chart.on(event, handler);
          }
        }
      });
      // 增加实例属性
      Object.defineProperties(this, {
        width: {
          configurable: true,
          get: () => {
            return this.delegateGet('getWidth');
          }
        },
        height: {
          configurable: true,
          get: () => {
            return this.delegateGet('getHeight');
          }
        },
        isDisposed: {
          configurable: true,
          get: () => {
            return !!this.delegateGet('isDisposed');
          }
        },
        computedOptions: {
          configurable: true,
          get: () => {
            return this.delegateGet('getOption');
          }
        }
      });
      this.chart = chart;
    },
    /* 初始化options属性变化监听 */
    initOptionsWatcher() {
      if (this.__unwatchOptions) {
        this.__unwatchOptions();
        this.__unwatchOptions = null;
      }
      if (!this.manualUpdate) {
        this.__unwatchOptions = this.$watch(
          'options',
          (val, oldVal) => {
            if (!this.chart && val) {
              this.init();
            } else {
              this.chart.setOption(val, val !== oldVal);
            }
          },
          {deep: !this.watchShallow}
        );
      }
    },
    /* 显式修改options */
    mergeOptions(options, notMerge, lazyUpdate) {
      if (this.manualUpdate) {
        this.manualOptions = options;
      }
      if (!this.chart) {
        this.init(options);
      } else {
        this.delegateMethod('setOption', options, notMerge, lazyUpdate);
      }
    },
    /* 刷新echarts */
    refresh() {
      if (this.chart) {
        this.destroy();
        this.init();
      }
    },
    /* 销毁echarts */
    destroy() {
      this.dispose();
      this.chart = null;
    },
    /* echarts实例方法 */
    resize(options) {
      this.delegateMethod('resize', options);
    },
    appendData(params) {
      this.delegateMethod('appendData', params);
    },
    clear() {
      this.delegateMethod('clear');
    },
    showLoading(type, options) {
      this.delegateMethod('showLoading', type, options);
    },
    hideLoading() {
      this.delegateMethod('hideLoading');
    },
    dispatchAction(payload) {
      this.delegateMethod('dispatchAction', payload);
    },
    convertToPixel(finder, value) {
      return this.delegateMethod('convertToPixel', finder, value);
    },
    convertFromPixel(finder, value) {
      return this.delegateMethod('convertFromPixel', finder, value);
    },
    containPixel(finder, value) {
      return this.delegateMethod('containPixel', finder, value);
    },
    getDataURL(options) {
      return this.delegateMethod('getDataURL', options);
    },
    getConnectedDataURL(options) {
      return this.delegateMethod('getConnectedDataURL', options);
    },
    dispose() {
      this.delegateMethod('dispose');
    },
    /* 调用echarts实例方法 */
    delegateMethod(name, ...args) {
      if (!this.chart) {
        this.init();
      }
      return this.chart[name](...args);
    },
    /* 获取echarts属性 */
    delegateGet(methodName) {
      if (!this.chart) {
        this.init();
      }
      return this.chart[methodName]();
    }
  },
  /* echarts静态方法 */
  connect(group) {
    if (typeof group !== 'string') {
      group = group.map(chart => chart.chart);
    }
    echarts.connect(group);
  },
  disconnect(group) {
    echarts.disconnect(group);
  },
  getMap(mapName) {
    return echarts.getMap(mapName);
  },
  registerMap(mapName, geoJSON, specialAreas) {
    echarts.registerMap(mapName, geoJSON, specialAreas);
  },
  registerTheme(name, theme) {
    echarts.registerTheme(name, theme);
  },
  graphic: echarts.graphic
}
</script>

<style>
.ele-charts > div:first-child {
  max-width: 100%;
  overflow: hidden;
}
</style>
