/**
 * @author  daya
 * @createDate  2021/11/12 18:17
 * 备注:图表逻辑公共处理部分
 **/
import common from './common'
import * as echarts from 'echarts'
// eslint-disable-next-line no-unused-vars
import {autoHover} from './auto-tooltip'
// eslint-disable-next-line no-unused-vars
import {barOption} from './components/bar/ts-vue-bar-style-1'
// eslint-disable-next-line no-unused-vars
import {lineOption} from './components/line/ts-vue-line-style-1'
// import {optStyle, colorStyle, seriesStyle, chartConfig} from './index'
/** 图表配置（包括xAxisName: 'style1',
 * *    yAxisName: 'style1',
 * *    tooltipName: 'style1',
 * *    legendName: 'style1',
 * *    seriesName: 'style1',
 * *    colorName: 'style1',）
 *    */
let chartConfig = {}
// 图表预设颜色
let colorStyle = {}
// 图表预设样式
let optStyle = {}
// 图表预设颜色
let seriesStyle = {}
export const chartMinxin = {
  props: {
    chartRef: {
      default: 'chart' + common.uuid(),
      type: String
    },
    // 图表数据
    data: {
      default: () => ({
        axisList: [],
        dataList: [
          {name: '', data: []},
          {name: '', data: []}
        ]
      })
    },
    // 基本样式选择
    styleName: {
      default: 'style1',
      type: String
    },
    // 颜色选择
    colorName: {
      default: '',
      type: String
    },
    // series样式选择
    seriesName: {
      default: '',
      type: String
    },
    // 超过多长开启滚动条
    dataZoomLen: {
      type: Number,
      default: 8
    },
    /**
     *  这个是为了预设样式没有出来，但原有的图表满足互相拼装组成新的图表而采用的，并且能减少一些不常用的预设样式
     *  常用需要修改的配置：
     *  以styleName为基本，
     *  根据预设的 toolTip (提示框组件)、xAxis(x轴)、yAxis(y轴)、legend(图例文字)
     *  注意：seriesName、colorName,dataZoomLen 也可以通过这个配置，但是如果其他不变更，只更改这两个的话，建议不要使用commonConfig
     *  超过多长进行滚动操作：滚动条配置(dataZoomLen: 10)
     *  自动高亮循环 ： 数量 tooltipNum: 10, 时间 tooltipTime: 1000
     *  示例：
     *  commonConfig: {
     *    open: true,
     *    xAxisName: 'style1',
     *    yAxisName: 'style1',
     *    tooltipName: 'style1',
     *    legendName: 'style1',
     *    seriesName: 'style1',
     *    colorName: 'style1',
     *    dataZoomLen: 10,
     *    tooltipNum: 10
     *  }
     */
    commonConfig: {
      type: Object,
      default: () => ({
        open: false,
        tooltipTime: 1000,
        tooltipNum: 0
      })
    },
    /**
     * 图表配置样式外部传入，默认不开启
     * 这个是为了预设样式没有出来，但原有的图表也不能满足互相拼装组成新的图表而采用的
     * 可以紧急让开发者自行设置图表全样式
     * **/
    optConfig: {
      type: Object,
      default: () => ({
        open: false,
        option: {}
      })
    },
    // 开启缩放的长度
    zoomSize: {
      default: 0,
      type: Number
    },
    // 自定义样式覆盖配置
    customConfig: {
      type: Object,
      default: () => ({
        open: false
      })
    }
  },
  data () {
    return {
      chart: null,
      // 图表设置
      option: {},
      fnResize: ''
    }
  },
  watch: {
    // 图表数据
    data (value) {
      if (this.chart) {
        this.reloadChart()
      }
    },
    styleName () {
      this.reloadChart()
    },
    seriesName () {
      this.reloadChart()
    },
    dataZoomLen () {
      this.reloadChart()
    },
    commonConfig () {
      this.reloadChart()
    },
    optConfig () {
      this.reloadChart()
    },
    customConfig () {
      this.reloadChart()
    }
  },
  async beforeCreate () {
  },
  async created () {
  },
  async beforeMount () {
    // console.log('执行顺序3')
  },
  // mounted
  async mounted () {
    // console.log('执行顺序1')
    let self = await this.setThat()
    /** 特殊操作，后面这个这个怎么搞合适
     * 1.给body设置了room属性。
     * 2.然后某个页面引入了echarts，悬浮发生了错位。
     * 3.解决办法：既然body缩放了，那么渲染echarts图表的div再给他放大回去就好了。
     **/
    let scope = localStorage.getItem('scope')
    if (scope && scope !== '100') {
      var t = 100 / parseInt(scope)
      self.$refs[self.chartRef].style.zoom = 1 / t
    }
    // 图表初始化之前
    await self.beforeInitEchart()
    await self.initChart()
    // 渲染图表
    await self.renderCharts()
    await self.setFontSize()
    // 屏幕大小缩放的时候，重新调整图表的大小
    // window.addEventListener('resize', this.chart.resize)
    self.observerFatherDomSize()
    self.resizeEcharts()
    await self.setZoomSize()
    self.setAutoTooltip()
    // console.log('执行顺序4')
  },
  // 销毁前
  async beforeDestroy () {
    let self = await this.setThat()
    // 注销监听事件listenResizeFn
    common.removeResizeEvent(self.fnResize)
    if (self.option.xAxis) {
      self.option.xAxis.data = []
    }
    if (self.option.yAxis) {
      self.option.yAxis.data = []
    }
    self.option.series.forEach(item => {
      item.data = []
    })
    self.chart.dispose()
  },
  methods: {
    async setThat () {
      let self = this
      return self
    },
    // 根据图表类型设置加载不同的图表配置
    async setChartConfig () {
      optStyle = await common.deepCopy(this.optStyle)
      colorStyle = await common.deepCopy(this.colorStyle)
      seriesStyle = await common.deepCopy(this.seriesStyle)
      chartConfig = await common.deepCopy(this.chartConfig)
      // let self = await this.setThat()
      // let type = self.type
      // let chartOption = ''
      // switch (type) {
      //   case 'bar':
      //     chartOption = await common.deepCopy(barOption)
      //     optStyle = await common.deepCopy(barOption['optStyle'])
      //     colorStyle = await common.deepCopy(barOption['colorStyle'])
      //     seriesStyle = await common.deepCopy(barOption['seriesStyle'])
      //     chartConfig = await common.deepCopy(barOption['chartConfig'])
      //     break
      //   case 'line':
      //     console.log('barOption', barOption)
      //     chartOption = await common.deepCopy(lineOption)
      //     optStyle = await common.deepCopy(lineOption['optStyle'])
      //     colorStyle = await common.deepCopy(lineOption['colorStyle'])
      //     seriesStyle = await common.deepCopy(lineOption['seriesStyle'])
      //     chartConfig = await common.deepCopy(lineOption['chartConfig'])
      //     break
      //   default:
      //     break
      // }
      // if (chartOption) {
      //   // optStyle = await common.deepCopy(chartOption['optStyle'])
      //   // colorStyle = await common.deepCopy(chartOption['colorStyle'])
      //   // seriesStyle = await common.deepCopy(chartOption['seriesStyle'])
      //   // chartConfig = await common.deepCopy(chartOption['chartConfig'])
      // }
    },
    // 重新加载图表
    async reloadChart () {
      let self = await this.setThat()
      if (self.chart) {
        self.renderCharts()
      }
    },
    // 初始化图表
    async initChart () {
      let self = await this.setThat()
      if (!self.chart) {
        // dark, light
        self.chart = echarts.init(self.$refs[self.chartRef], '', {renderer: 'canvas'})
        self.chart.setOption(self.option)
      }
    },
    // 初始化图表之前
    async beforeInitEchart () {
      let self = await this.setThat()
      // 根据图表类型设置加载不同的图表配置
      await self.setChartConfig()
      // 将图表类型的首字母转换为大写
      let styleName = await common.letterFrist2UpperCase(self.styleName)
      self.option = await common.deepCopy(optStyle['option' + styleName])
    },
    // 渲染图表
    async renderCharts () {
      let self = await this.setThat()
      if (!self.chart) {
        return
      }
      if (self.chart) {
        self.chart.clear()
      }
      // 将图表类型的手字母转换为大写
      let styleName = await common.letterFrist2UpperCase(self.styleName)
      self.option = await common.deepCopy(optStyle['option' + styleName])
      // 区分横轴
      let yAxis = await common.deepCopy(self.option.yAxis)
      if ((Array.isArray(yAxis) &&
        yAxis[0].type === 'value') ||
        yAxis.type === 'value') {
        // 纵向
        self.option.xAxis.data = self.data.axisList ? await common.deepCopy(self.data.axisList) || [] : []
        // console.log('纵向1')
      } else {
        // 横向
        self.option.yAxis.data = self.data.axisList ? await common.deepCopy(self.data.axisList) || [] : []
        // console.log('横向')
      }
      let dataList = self.data.dataList ? await common.deepCopy(self.data.dataList) || [] : []
      if (dataList.length) {
        let seriesList = []
        let seriesData = {}
        // 如果seriesName存在这拿seriesName，不存在则拿styleName预设样式
        if (self.seriesName) {
          let seriesName = await common.letterFrist2UpperCase(self.seriesName)
          seriesData = await common.deepCopy(seriesStyle['series' + seriesName])
        } else {
          seriesData = await common.deepCopy(optStyle['option' + styleName].series[0])
        }
        self.data.dataList.forEach((item, index) => {
          let seriesItem = {
            ...seriesData,
            name: item.name,
            data: item.data || item.ratio || item.value || [],
            ratio: item.ratio || item.value || []
          }
          seriesList.push(seriesItem)
        })
        self.option.series = seriesList
        // 修改颜色
        if (self.colorName) {
          let colorName = await common.letterFrist2UpperCase(self.colorName)
          self.option.color = await common.deepCopy(colorStyle['color' + colorName])
        }
        // if (self.data.axisList.length) {
        //   setDataZoom(self.option, self.data.axisList.length, self.dataZoomLen)
        // }
        // 如果存在修改配置，则先修改配置 （根据预设样式的）
        if (self.commonConfig.open) {
          self.option = await common.changeChartOpt(self.option, self.commonConfig, self.data, chartConfig)
        }
        // 如果是外部配置的图表option,这深拷贝赋值给option，无需结合任何配置
        if (self.optConfig.open) {
          self.option = await common.deepCopy(self.optConfig.option)
        }
        // console.log('self.option', JSON.stringify(self.option))
        self.chart.setOption(self.option)
      }
    },
    // 添加父元素尺寸变化监听事件（后续要不要加个节流事件）
    async observerFatherDomSize () {
      let self = await this.setThat()
      // 定义ResizeObserver对象，并设置监听方法
      const myObserver = new ResizeObserver(entry => {
        if (self.chart) {
          self.chart.resize()
        }
      });
      // 添加要监听的元素，把echart的container div添加为监听对象
      if (self.$refs[self.chartRef]) {
        myObserver.observe(self.$refs[self.chartRef]);
      }
    },
    // 添加监听事件listenResizeFn
    async resizeEcharts () {
      let self = await this.setThat()
      self.fnResize = () => {
        if (self.chart) {
          self.setFontSize()
          console.log('添加监听事件listenResizeFn')
          self.chart.resize()
        }
      }
      common.addResizeEvent(self.fnResize)
    },
    // 配置点击点击缩放
    async setZoomSize () {
      let self = await this.setThat()
      if (!self.zoomSize) {
        return
      }
      let data = await common.deepCopy(self.data.dataList[0].data)
      let dataAxis = await common.deepCopy(self.data.axisList)
      let zoomSize = self.zoomSize
      self.chart.on('click', function (params) {
        self.chart.dispatchAction({
          type: 'dataZoom',
          startValue: dataAxis[Math.max(params.dataIndex - zoomSize / 2, 0)],
          endValue:
            dataAxis[Math.min(params.dataIndex + zoomSize / 2, data.length - 1)]
        })
      })
    },
    // 预留的滚动
    async setScrollBar (totalLen, showLen) {
      let self = await this.setThat()
      let zoomSlider = self.option.dataZoom[0]
      if (totalLen <= showLen) {
        zoomSlider.show = false
        zoomSlider.start = 0
      } else {
        zoomSlider.show = true
        zoomSlider.start = Math.ceil((totalLen - showLen) / totalLen * 100)
      }
    },
    // 如果自定义的配置生效，则option原本没有存在这个属性没有就赋值,有就替换这个值
    async setCustomConfig () {
      let self = this
      // 如果自定义的配置生效，则option原本没有存在这个属性没有就赋值,有就替换这个值
      if (self.customConfig.open) {
        self.option = await this.chart.getOption()
        self.option = await common.changeChartOptByCustomConfig(self.option, self.customConfig)
        self.chart.setOption(self.option)
      }
      return self.option
    },
    // 设置字体大小， 主要是为了解决实时响应，不用实时响应的话，直接fontSize(12)就行了
    // TODO：(更好的解决办法参考：https://zhuanlan.zhihu.com/p/519926571)
    async setFontSize () {
      let self = this
      self.option = await self.fontSizeFormatter(self.option)
      self.chart.setOption(self.option)
    },
    // 循环找到fontSizeFormatter并修改fontSize的值
    async fontSizeFormatter (option) {
      if (option === {}) {
        return option
      }
      for (let customKey in option) {
        if (customKey !== 'customKey') {
          // 如果是对象
          let customStr = option[customKey]
          if (typeof customStr === 'object') {
            // 如果被赋值的是对象
            if (Array.isArray(option[customKey])) {
              for (var i = 0; i < customStr.length; i++) {
                await this.fontSizeFormatter(option[customKey][i])
                break
              }
            } else {
              await this.fontSizeFormatter(option[customKey])
            }
          } else {
            if (customKey === 'fontSizeFormatter') {
              option['fontSize'] = await option[customKey]()
              // console.log(' option[\'fontSize\']',  option['fontSize'])
            }
          }
        }
      }
      return option
    },
    async setAutoTooltip () {
      /**
       * autoHover(初始的实例化对象, 设置的参数对象, 轮询的数据点数, 轮询间隔/单位ms)
       * 初始的实例化对象和设置的参数对象---上放图表咋命名就写啥
       * 轮询的数据点数---循环时达到最大值后，使其从头开始循环,所以是数据点数
       * 轮询间隔/单位ms---如果数据点多可以设置小一点，一般为1000即一秒
       * **/
      let self = this
      if (self.commonConfig.open && self.commonConfig.tooltipNum) {
        let num = self.commonConfig.tooltipNum
        let time = self.commonConfig.tooltipTime
        await autoHover(self.chart, self.option, num, time)
      }
    }
  }
}
