<template>
  <div class="d-flex" style="width: 100%;">
    <!-- 模板列表 -->
    <chartList ref="chartListRef" @chartTypeChange="chartTypeChange"/>
    <div class="flex-grow-1" style="overflow: hidden;">
      <div class="elevation-2 px-5 mb-3 d-flex justify-space-between align-center" style="height: 60px; background-color: #fff;">
        <!-- 名称 -->
        <div class="d-flex align-center"><span>图表名称：</span><v-text-field v-model="chartNickname" class="input-width-m" hide-details dense outlined></v-text-field></div>
        <!-- 保存按钮 -->
        <v-btn class="half-button" color="primary" @click="save">保存</v-btn>
      </div>
      <div class="pa-5" style="width: 100%; background-color: #eee;">
        <!-- 表格 -->
        <div v-if="chartType === 'table'" :id="id + 'table'" class="pa-2 pt-8" style="height: calc(100vh - 186px);background-color: #fff;">
          <tableShow
            ref="tableShowRef"
            :useField="useField"
            :fieldInfo="useField ? fieldInfo : null"
            :excelData="useField ? null : excelData"
            :headerEnNames="headerEnNames"
          ></tableShow>
        </div>
        <!-- chart图例 -->
        <div v-else style="width: 100%;">
          <div v-show="!showEmpty" :id="id" class="pa-2 pt-8" style="height: calc(100vh - 186px);background-color: #fff; width: 100%"></div>
          <div v-show="showEmpty" class="emptyBox">无可用数据</div>
        </div>
      </div>
    </div>
    <!-- 配置 -->
    <div ref="settingRef" class="elevation-2 ml-4 d-flex flex-column" style="width: 600px;">
      <div>
        <v-tabs v-model="activeIndex" @change="handleChange">
          <v-tab>数据</v-tab>
          <v-tab>配置</v-tab>
          <v-tab>数据探索</v-tab>
        </v-tabs>
      </div>
      <!-- 数据 -->
      <div v-show="activeIndex === 0">
        <div class="d-flex pa-3" v-if="!disabled">
          <span style="font-size: 16px;">使用动态数据</span>
          <v-switch
            dense
            hide-details
            :disabled="disabled"
            class="mt-0 ml-2 pa-0"
            v-model="useField"
            color="primary"
            @mousedown.native.prevent="handleFieldChange"
          ></v-switch>
        </div>
        <div class="py-3" style="height: calc(100vh - 200px); overflow-y: auto;">
          <!-- 数据域及过滤信息 -->
          <data-field v-if="useField" ref="dataField" :fieldProps="fieldInfo" @change="fieldChange"></data-field>
          <!-- <div class="pa-3" v-if="useField"><span style="color: #ff5252;">注：使用动态数据生成的表格不可编辑。</span></div> -->
          <!-- excelData准备完毕后再显示MExcel，避免多次触发change事件 -->
          <!-- <MExcel v-if="excelData" :data="excelData" :showTools="!useField" :readOnly="useField" @change="excelDataChange" class="px-3"></MExcel> -->
          <!-- <component :is="mExcel" v-if="excelData" :data="excelData" :showTools="!useField" :readOnly="useField" @change="excelDataChange" class="px-3"></component> -->
        </div>
      </div>
      <!-- 配置 -->
      <div v-show="activeIndex === 1">
        <table-settings v-if="chartType === 'table'" ref="tableSettingsRef" :list="XYList" @change="tableHeaderChange"></table-settings>
        <general-settings v-else ref="generalSettingsRef" :type="chartType" :xList="xList" :yList="yList" :xChosen="xChosen" :yChosen="yChosen" @change="handleGeneralChange"></general-settings>
      </div>
      <div v-show="activeIndex === 2" style="flex: 1;height: 0;">
        <MTalk :type="2" @change="handleChangeTalk"></MTalk>
      </div>
    </div>
  </div>
</template>

<script>
// import MDialog from '@/components/Dialog'
import html2canvas from 'html2canvas'
import { uploadFile } from '@/api/user'
import chartList from './components/chartList.vue'
import chartListData from './components/utils/chartList'
// import MExcel from '@/components/MExcel'
import dataField from './components/dataField.vue'
import tableSettings from './components/tableSettings.vue'
import generalSettings from './components/generalSettings.vue'
import tableShow from './components/tableShow.vue'
import { dealExcelToSettingList } from './components/utils/dataDeal'
import { generateUUID } from '@/utils'
import { getDrillingData } from './components/utils/getFieldData'
import cloneDeep from 'lodash/cloneDeep'
import MTalk from '@/components/Knowledge/talk'
export default {
  name: 'edit-index',
  components: {
    // ToolTip,
    // MDialog,
    chartList,
    tableSettings,
    generalSettings,
    tableShow,
    // MExcel,
    dataField,
    MTalk
  },
  props: {
    rowObj: {
      type: Object,
      default: () => {}
    }
  },
  computed: {},
  data () {
    return {
      mExcel: null,
      disabled: false,
      chartListData,
      review: false,
      pieXEnName: '',
      isEdit: false,
      fieldInfo: {}, // 回显数据域信息
      showEmpty: false,
      useField: false, // 使用数据域
      chartNickname: '定制图表',
      id: generateUUID(),
      // show: false,
      xList: null,
      yList: null,
      xChosen: 0,
      yChosen: [],
      XYList: [],
      headerEnNames: [], // 英文字段
      excelData: null,
      defaultExcelData: [
        ['date', 'Fantasy', 'Toyota', 'Ford', 'Honda', 'Volvo', 'Amos', 'Yisrael'],
        ['2018', '150', '230', '232', '233', '135', '143', '260'],
        ['2019', '230', '232', '233', '135', '143', '260', '150'],
        ['2020', '230', '233', '135', '143', '260', '150', '230'],
        ['2021', '230', '135', '143', '260', '150', '230', '232'],
        ['2022', '142', '143', '260', '150', '230', '232', '233'],
        ['2023', '142', '260', '150', '230', '232', '233', '135'],
        //
        // ['2018', '150', '230', '232', '233', '135', '143', '260'],
        // ['2019', '230', '232', '233', '135', '143', '260', '150'],
        // ['2020', '230', '233', '135', '143', '260', '150', '230'],
        // ['2021', '230', '135', '143', '260', '150', '230', '232'],
        // ['2022', '142', '143', '260', '150', '230', '232', '233'],
        // ['2023', '142', '260', '150', '230', '232', '233', '135'],
        //
        ['2024', '260', '150', '230', '232', '233', '135', '143']
      ],
      chartOption: {},
      chartType: '',
      chart: null,
      activeIndex: 0
      // isIE: navigator.userAgent.indexOf('MSIE') > -1 || navigator.userAgent.indexOf('Trident') > -1
    }
  },
  created () {
    // if (!this.isIE) {
    //   import('@/components/MExcel')
    //     .then(module => {
    //       this.mExcel = module.default // 获取组件并赋值
    //     })
    //     .catch(err => {
    //       console.error('Failed to load component:', err)
    //     })
    // }
    if (Object.keys(this.rowObj).length) {
      this.isEdit = true
      this.review = true
      this.chartType = this.rowObj.content.type
      this.chartOption = cloneDeep(this.rowObj.content.option)
      this.chartNickname = this.rowObj.content.name
      this.useField = this.rowObj.content.useField
      if (this.useField) {
        // 动态数据（数据域）
        this.fieldInfo = this.rowObj.content.fieldInfo
      } else {
        this.activeIndex = 2
        // Excel表格
        let excel = this.rowObj.content.excelData
        if (typeof excel === 'string') excel = JSON.parse(excel)
        else if (!excel || !excel.length) excel = [[]]
        this.excelData = excel
        // console.log(this.rowObj)
      }
    } else {
      const chartInit = this.chartListData[0].children[0]
      this.chartType = this.chartListData[0].value
      // this.chartType = chartInit.value
      this.chartOption = cloneDeep(chartInit.option) // 不能改变模板数据
      this.excelData = this.defaultExcelData || [[]]
      this.useField = true
    }
    this.$nextTick(() => {
      this.disabled = true
      if (this.chartType !== 'table') {
        this.chart = this.$echarts.init(document.getElementById(this.id))
        this.chart.setOption(this.chartOption)
      }
    })
  },
  mounted () {
  },
  watch: {},
  methods: {
    handleChange (index) {
      this.useField = index !== 2
    },
    // 探索返回表格数据
    handleChangeTalk (headers, body) {
      const data = [
        headers,
        ...body.map(e => Object.values(e))
      ]
      // console.log(data)
      this.excelDataChange(data)
    },
    // 模板切换事件
    chartTypeChange (item, chartType) {
      this.chartType = chartType
      if (this.chartType === 'table') {
        this.chart = null
        this.headerEnNames = this.XYList.map(e => e.value) // 数据域改变-table表头更改
        this.$nextTick(() => {
          this.$refs.tableSettingsRef.chosen = this.XYList.map((_, index) => index)
          this.$refs.tableShowRef.headers = this.XYList.map(e => e)
          this.$refs.tableShowRef.upDate('chartTypeChange') // table更新事件
        })
        return
      }
      this.chartOption = cloneDeep(item.option) // 不能改变模板数据
      this.xChosen = 0; this.yChosen = [0] // 重置配置选项
      if (!this.xList?.length) this.setXYData(this.XYList) // 编辑表格时切换chart没有xy数据
      this.$nextTick(() => {
        if (!this.chart) this.chart = this.$echarts.init(document.getElementById(this.id))
        this.setOptionData()
        this.setChart()
      })
    },
    // 切换数据域
    handleFieldChange () {
      if (this.useField) {
        // 取消关联数据域提示
        this.$confirm('提示', '是否取消使用动态数据？').then(() => {
          // 删除数据域信息
          this.fieldInfo = {}
          this.useField = false
          this.excelDataChange(this.excelData) // 重新生成配置数据，唯一标识会与Excel不同
        }).catch(e => {})
      }
    },
    // 表头配置
    tableHeaderChange (chosen) {
      if (!chosen?.length) return
      this.$refs.tableShowRef.headers = chosen.map(e => this.XYList[e]).filter(i => i)
      this.$refs.tableShowRef.upDate('tableHeaderChange') // table更新事件
    },
    // XY配置change
    handleGeneralChange (type, val) {
      if (!this.xList?.length) return
      if (this.chartType === 'pie') {
        // 饼图
        this.chartOption.series[0].data = []
        if ((val.x || val.x === 0) && val.y) {
          this.xChosen = val.x; this.yChosen = val.y
          this.chartOption.series[0].name = this.yList[val.y[0]].name
          this.chartOption.series[0].fieldValue = this.yList[val.y[0]].value
          this.pieXEnName = this.xList[val.x].value
          this.xList[val.x].data.forEach((item, index) => {
            const obj = { value: this.yList[val.y[0]].data[index], name: item }
            this.chartOption.series[0].data.push(obj)
          })
        }
        this.setChart()
        return
      }
      if (type === 'y' && val.y) {
        this.yChosen = val.y
        const series = []
        val.y.forEach(item => {
          const obj = this.yList[item]
          if (!obj) return
          const seriesItem = this.chartOption.series.find(series => series.fieldValue === obj.value)
          if (seriesItem) series.push(seriesItem)
          else series.push({ data: obj.data, name: obj.name, fieldValue: obj.value, type: this.chartType })
        })
        this.chartOption.series = series
      }
      if (type === 'x' && (val.x || val.x === 0)) {
        this.xChosen = val.x
        const x = this.xList[val.x]
        Object.assign(this.chartOption.xAxis, { name: x.text, fieldValue: x.value, data: x.data })
      }
      this.setChart()
    },
    tableUpdate (type) {
      const vm = this
      let newheaderEnNames = []; let headers = []; const chosen = []
      if (type) { // type=0:过滤与排序表头不变
        // 回显，且原本的数据就是表格数据
        if (this.review && this.rowObj.content.headerEnNames?.length) review()
        else selectAll()
        this.headerEnNames = newheaderEnNames
        this.review = false
        this.$nextTick(() => {
          this.$refs.tableShowRef.headers = headers
          this.$refs.tableSettingsRef.chosen = chosen
        })
      }
      this.$nextTick(() => {
        if (type === 2) this.$refs.tableShowRef.analyzingEexel()
        else this.$refs.tableShowRef.getFieldData() // 数据域改变-table更新事件
      })

      function review () {
        const headerEnNames = vm.rowObj.content.headerEnNames || []
        newheaderEnNames = headerEnNames.map(e => {
          const index = vm.XYList.findIndex(j => j.value === e)
          if (index > -1) {
            chosen.push(index)
            headers.push(vm.XYList[index])
            return e
          } else return null
        }).filter(f => f)
      }
      function selectAll () {
        // const chosen = []; const newheaderEnNames = []; let headers = []
        headers = vm.XYList.map((item, index) => {
          chosen.push(index)
          newheaderEnNames.push(item.value)
          return item
        })
      }
    },
    // 数据域数据转表格数据
    fieldChange (type, fieldInfo) {
      const vm = this; let obj
      this.excelData = [[]]
      if (type === 'field_change') { // 数据域Change
        this.xList = []; this.yList = []; this.XYList = []
        this.xChosen = 0; this.yChosen = [0] // 重置配置选项
        getDrillingData(1, { fieldInfo }).then(res => { // fieldInfo：只需要fieldId
          obj = res
          setData()
          this.chartType === 'table' ? this.tableUpdate(1) : this.initChart()
        }).catch(e => {})
      } else if (type === 'filter_change') {
        // 过滤与排序Change
        getDrillingData(2, { fieldInfo, XYList: vm.XYList }).then(res => { // fieldInfo：需要fieldId、fieldEngName、metaItemEngNames
          obj = res
          setData()
          this.chartType === 'table' ? this.tableUpdate(0) : this.initChart()
        }).catch(e => {})
      }
      function setData () {
        vm.XYList = obj.XYList
        if (obj.metaData) vm.$refs.dataField.$refs.filterRef.metaData = obj.metaData
        vm.fieldInfo = obj.fieldInfo
        vm.excelData = obj.excelData
      }
    },
    // 表格数据change
    excelDataChange (array) { // Excel改变
      if (this.useField) return // 处理数据域数据不在此触发
      this.xList = []; this.yList = []
      this.xChosen = 0; this.yChosen = [0] // 重置配置选项
      this.XYList = dealExcelToSettingList(array)
      if (this.chartType === 'table') {
        this.tableUpdate(2) // table更新事件
      } else {
        this.initChart()
      }
    },
    initChart () {
      const list = this.XYList
      if (list && list.length) {
        this.showEmpty = false
        this.setXYData(list)
        this.setOptionData()
      } else {
        // 表格无数据显示
        if (this.chartType === 'pie') {
          this.chartOption.series[0].fieldValue = ''
          this.chartOption.series[0].name = ''
          this.chartOption.series[0].data = []
        } else {
          Object.assign(this.chartOption.xAxis, { fieldValue: '', name: '', data: [] })
          this.chartOption.series.forEach(e => { e.fieldValue = ''; e.name = ''; e.data = [] })
        }
        if (this.useField) this.showEmpty = true // 提示数据域返回数据为空showEmpty
      }
      this.setChart()
    },
    // 表格生成chart x、series【data】数据
    setXYData (list) {
      this.xList = list
      // y轴非数值的键值对往后放
      const yInit = [...list.slice(1)] // 创建一个新数组，除了第一个元素之外，其余元素与原数组相同
      const yArr1 = yInit.filter(item => item.hasNum)
      const yArr2 = yInit.filter(item => !item.hasNum)
      this.yList = yArr1.concat(yArr2)
      this.yList.push(list[0]) // 将原数组的第一个元素添加到新数组的末尾
    },
    // 往chart填充数据
    setOptionData () {
      if (this.chartType === 'table') return
      if (!Object.keys(this.chartOption).length) return
      if (this.chartType === 'pie') {
        // 饼图
        const pieZeroSeries = this.chartOption.series[0]
        pieZeroSeries.data = []
        let xIndex = 0; let yIndex = 0
        if (this.rowObj.content?.pieXEnName) xIndex = this.xList.findIndex(key => key.value === this.rowObj.content.pieXEnName)
        if (pieZeroSeries.fieldValue) yIndex = this.yList.findIndex(key => key.value === pieZeroSeries.fieldValue)
        xIndex = xIndex > 0 ? xIndex : 0
        yIndex = yIndex > 0 ? yIndex : 0
        this.xChosen = xIndex
        this.yChosen = [yIndex]
        const x = this.xList[xIndex]
        const y = this.yList[yIndex]
        pieZeroSeries.name = y.name
        pieZeroSeries.fieldValue = y.value
        this.pieXEnName = x.value
        x.data.forEach((item, index) => {
          const obj = { value: y.data[index], name: item }
          pieZeroSeries.data.push(obj)
        })
      } else { // 柱状图折线图
        const xAxis = this.chartOption.xAxis
        let xIndex = 0
        if (xAxis.fieldValue) xIndex = this.xList.findIndex(key => key.value === xAxis.fieldValue)
        xIndex = xIndex > 0 ? xIndex : 0
        this.xChosen = xIndex
        // xAxis 数据
        const x = this.xList[xIndex]
        Object.assign(xAxis, { name: x.text, fieldValue: x.value, data: x.data })
        // series 数据
        this.yChosen = [] // 清空之前数据
        this.chartOption.series.forEach((item, index) => {
          let yIndex = index // name不一定存在,所以默认为index
          if (item?.fieldValue) yIndex = this.yList.findIndex(key => key?.value === item?.fieldValue)
          if (yIndex < 0) yIndex = index
          this.yChosen.push(yIndex) // 默认已选择展示的数据
          if (this.yList[yIndex]) {
            item.fieldValue = this.yList[yIndex].value
            item.name = this.yList[yIndex].name
            item.data = this.yList[yIndex].data
          }
        })
      }
    },
    // 渲染chart
    setChart () {
      this.$nextTick(() => {
        if (this.chart) this.chart.clear()
        if (this.chart) this.chart.setOption(this.chartOption)
      })
    },
    async save () { // 保存
      if (this.useField && !this.$refs.dataField.$refs.formRef.validate()) return // 打开数据域后数据域必填检验
      // 保存图片
      const id = this.chartType === 'table' ? this.id + 'table' : this.id
      // const dom = document.getElementById(id)
      let dom = null
      if (this.chartType === 'table') dom = this.$refs.tableShowRef.$refs.tableRef.$refs.table.$el.childNodes[0].childNodes[0]
      else dom = document.getElementById(id)
      const canvas = await html2canvas(dom)
      const base64Image = canvas.toDataURL('image/png')
      // console.log('base64Image', base64Image)
      const imageFile = this.base64ToFile(base64Image, 'image.png')

      const content = {
        name: this.chartNickname,
        enName: 'chartCustomizedCreate', // 英文名称暂时用不上，默认写死占位
        type: this.chartType,
        // option: this.chartOption,
        useField: this.useField
      }
      try {
        // 保存图片
        const { data } = await uploadFile('data/', imageFile)
        content.coverImg = data?.url || ''

        if (!this.useField) content.excelData = JSON.stringify(this.excelData)
        if (this.useField) content.fieldInfo = this.fieldInfo
        if (this.chartType === 'pie') content.pieXEnName = this.pieXEnName
        if (this.chartType === 'table') content.headerEnNames = this.$refs.tableShowRef.headers.map(e => e.value)
        else content.option = this.chartOption
        const obj = {
          code: this.rowObj.code ? this.rowObj.code : content.name + generateUUID(),
          webSettingCategory: 'chartList',
          content
        }
        if (this.rowObj.webSettingId) Object.assign(obj, { webSettingId: this.rowObj.webSettingId })
        this.$emit('submit', obj)
      } catch (error) {
        this.$snackbar.error(error)
      }
    },
    // 64转file
    base64ToFile (base64Data, filename) {
      // 提取base64的数据部分
      const parts = base64Data.split(';base64,')
      const contentType = parts[0].split(':')[1]
      const raw = window.atob(parts[1])
      // 将原始数据转换为Uint8Array
      const rawLength = raw.length
      const uInt8Array = new Uint8Array(rawLength)
      for (let i = 0; i < rawLength; ++i) {
        uInt8Array[i] = raw.charCodeAt(i)
      }
      // 创建Blob对象
      const blob = new Blob([uInt8Array], { type: contentType })
      // 创建File对象
      return new File([blob], filename, { type: contentType })
    }
  }
}
</script>
<style lang="scss" scoped>
.emptyBox {
  height: calc(100vh - 186px);
  background-color: #fff;
  display: flex;
  justify-content: center;
  align-items: center;
}
</style>
