<template>
  <view class="ml-charts" :class="className" :style="{height: height || '400rpx', width: width || '100%'}">
    <canvas ref="canvasRef" class="ml-charts-canvas" :type="platformEnv.isZFBMP ? '' : '2d'" :id="canvasId" :canvas-id="canvasId" :width="cvsWidth" :height="cvsHeight" @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd"></canvas>
  </view>
</template>

<script>
import WxCanvas from '../ml-charts/wx-canvas'
import echarts from '../ml-charts/echarts'
import XEUtils from 'xe-utils'
import MaliUtils from '../../../utils'

function wrapTouch (event) {
  for (let i = 0; i < event.touches.length; ++i) {
    const touch = event.touches[i]
    touch.offsetX = touch.x
    touch.offsetY = touch.y
  }
  return event
}

export default {
  name: 'MlEcharts',
  props: {
    options: Object,
    height: String,
    width: String,
    lazyLoad: Boolean,
    formatLegend: Function,
    className: String
  },
  inject: {
    currVM: {
      from: '$pageVM',
      default: null
    }
  },
  data () {
    return {
      platformEnv: MaliUtils.getPlatformEnv(),
      canvasId: XEUtils.uniqueId('chart'),
      cvsWidth: '',
      cvsHeight: ''
    }
  },
  watch: {
    options () {
      this.loadChart()
    }
  },
  mounted  () {
    if (!this.lazyLoad) {
      this.init()
    }
  },
  beforeDestroy () {
    if (this.chart) {
      this.chart.dispose()
      this.chart = null
    }
  },
  methods: {
    getOptions () {
      const opts = this.options
      if (opts) {
        if (opts.legend && opts.legend.customFormat && this.formatLegend) {
          opts.legend.formatter = this.customFormat
        }
      }
      return opts
    },
    customFormat (name) {
      return this.formatLegend.call(this.currVM, name, this.options || {})
    },
    loadChart () {
      if (this.chart) {
        const option = this.getOptions()
        if (option) {
          this.chart.setOption(option, true)
        }
      }
    },
    init () {
      this.$nextTick(() => {
        if (this.platformEnv.isH5) {
          // #ifdef H5
          this.initWeb()
          // #endif
        } else if (this.platformEnv.isWXMP || this.platformEnv.isQWMP) {
          // #ifdef MP-WEIXIN
          this.initWxApplet()
          // #endif
        } else if (this.platformEnv.isDDMP || this.platformEnv.isZFBMP) {
          // #ifdef MP-ALIPAY
          this.initAlipyApplet()
          // #endif
        }
      })
    },

    // #ifdef H5
    initWeb () {
      const chart = echarts.init(this.$refs.canvasRef.$el.firstChild)
      this.chart = chart
      this.loadChart()
    },
    // #endif

    // #ifdef MP-WEIXIN
    initWxApplet () {
      echarts.registerPreprocessor(option => {
        if (option && option.series) {
          if (option.series.length > 0) {
            option.series.forEach(series => {
              series.progressive = 0
            })
          } else if (typeof option.series === 'object') {
            option.series.progressive = 0
          }
        }
      })
      const query = uni.createSelectorQuery().in(this)
      query
        .select(`#${this.canvasId}`)
        .fields({
          node: true,
          size: true,
          context: true
        })
        .exec(res => {
          if (res && res[0]) {
            const canvasNode = res[0].node
            const ratio = MaliUtils.getAppDpr()
            const canvasWidth = res[0].width
            const canvasHeight = res[0].height
            this.cvsWidth = canvasWidth
            this.cvsHeight = canvasHeight
            this.ctx = canvasNode.getContext('2d')
            const canvas = new WxCanvas(this.ctx, this.canvasId, true, canvasNode)
            echarts.setCanvasCreator(() => {
              return canvas
            })
            const chart = echarts.init(canvas, null, {
              width: canvasWidth,
              height: canvasHeight,
              devicePixelRatio: ratio
            })
            canvas.setChart(chart)
            this.chart = chart
            this.loadChart()
          }
        })
    },
    // #endif

    // #ifdef MP-ALIPAY
    initAlipyApplet () {
      this.ctx = uni.createCanvasContext(this.canvasId, this)
      const canvas = new WxCanvas(this.ctx, this.canvasId)
      echarts.setCanvasCreator(() => {
        return canvas
      })
      const query = uni.createSelectorQuery().in(this)
      const ratio = MaliUtils.getAppDpr()
      query
        .select(`#${this.canvasId}`)
        .boundingClientRect(res => {
          const cvsWidth = ratio * res.width
          const cvsHeight = ratio * res.height
          this.cvsWidth = cvsWidth
          this.cvsHeight = cvsHeight
          const chart = echarts.init(canvas, null, {
            width: res.width,
            height: res.height
          })
          canvas.setChart(chart)
          this.chart = chart
          this.loadChart()
        })
        .exec()
    },
    // #endif
    canvasToTempFilePath (opt) {
      // #ifdef MP-WEIXIN
      const query = uni.createSelectorQuery().in(this)
      query
        .select('.ml-canvas')
        .fields({
          node: true,
          size: true
        })
        .exec(res => {
          const canvasNode = res[0].node
          opt.canvas = canvasNode
          uni.canvasToTempFilePath(opt)
        })
      // #endif

      // #ifdef MP-ALIPAY
      if (!opt.canvasId) {
        opt.canvasId = this.canvasId
      }
      this.ctx.draw(true, () => {
        uni.canvasToTempFilePath(opt, this)
      })
      // #endif
    },
    touchStart (e) {
      if (this.chart && e.touches.length > 0) {
        const touch = e.touches[0]
        const handler = this.chart.getZr().handler
        handler.dispatch('mousedown', {
          zrX: touch.x,
          zrY: touch.y
        })
        handler.dispatch('mousemove', {
          zrX: touch.x,
          zrY: touch.y
        })
        handler.processGesture(wrapTouch(e), 'start')
      }
    },
    touchMove (e) {
      if (this.chart && e.touches.length > 0) {
        const touch = e.touches[0]
        const handler = this.chart.getZr().handler
        handler.dispatch('mousemove', {
          zrX: touch.x,
          zrY: touch.y
        })
        handler.processGesture(wrapTouch(e), 'change')
      }
    },
    touchEnd (e) {
      if (this.chart) {
        const touch = e.changedTouches ? e.changedTouches[0] : {}
        const handler = this.chart.getZr().handler
        handler.dispatch('mouseup', {
          zrX: touch.x,
          zrY: touch.y
        })
        handler.dispatch('click', {
          zrX: touch.x,
          zrY: touch.y
        })
        handler.processGesture(wrapTouch(e), 'end')
      }
    }
  }
}
</script>

<style lang="scss">
.ml-charts-canvas {
  width: 100%;
  height: 100%;
}
</style>
