<template>
  <div :class="[`${prefixCls}`,this.border?'':'no-border']">
    <div :class="[`${prefixCls}-toolbar`]"
         v-if="editable">
      <Divider type="vertical" />
      <Button type="text"
              size="small"
              @click="mergeCell">
        <Icon custom="vuc-icon-merge"
              size="18"></Icon>
      </Button>
      <Button type="text"
              size="small"
              @click="splitCells">
        <Icon custom="vuc-icon-split"
              size="18"></Icon>
      </Button>
      <Divider type="vertical" />
      <Button type="text"
              size="small"
              @click.stop="bordered(false)">
        <Icon custom="vuc-icon-border"
              size="18"></Icon>
      </Button>
      <Button type="text"
              size="small"
              @click.stop="unbordered()">
        <Icon custom="vuc-icon-noborder"
              size="18"></Icon>
      </Button>
      <Divider type="vertical" />
      <ColorPicker ref="colorPicker"
                   v-model="bgColor"
                   icon="md-color-fill"
                   @on-change="handleColorChange('background')"
                   alpha
                   recommend />
      <ColorPicker ref="fontColorPicker"
                   v-model="fontColor"
                   icon="logo-tumblr"
                   @on-change="handleColorChange('color')"
                   alpha
                   recommend />
      <Divider type="vertical" />
      <Button size="small"
              type="text"
              @click="setAlign('left')">
        <Icon custom="vuc-icon-left"
              size="18"></Icon>
      </Button>
      <Button size="small"
              type="text"
              @click="setAlign('center')">
        <Icon custom="vuc-icon-center"
              size="18"></Icon>
      </Button>
      <Button size="small"
              type="text"
              @click="setAlign('right')">
        <Icon custom="vuc-icon-right"
              size="18"></Icon>
      </Button>
      <Divider type="vertical" />
      <Button size="small"
              type="text"
              @click="setIndent(12)">
        <Icon custom="vuc-icon-increase"
              size="18"></Icon>
      </Button>
      <Button size="small"
              type="text"
              @click="setIndent(-12)">
        <Icon custom="vuc-icon-decrease"
              size="18"></Icon>
      </Button>
      <Divider type="vertical" />
      <Select v-model="fontSize"
              size="small"
              style="width:80px"
              @on-change="handleFontSizeChange">
        <Option v-for="(item,idx) in fontList"
                :value="item"
                :key="`fs${idx}`">{{ item }}</Option>
      </Select>
    </div>
    <vxe-table ref="vucExcel"
               border
               resizable
               :height="height-2"
               size="mini"
               :cell-style="cellStyle"
               :cell-class-name="cellClassName"
               :header-cell-style="headerCellStyle"
               :span-method="rowspanMethod"
               :data="tableData"
               :show-header="editable"
               :optimization="{scrollY:{rHeight:36}}"
               :mouse-config="editable?{ selected: true, checked: true }:undefined"
               :keyboard-config="editable?{isArrow: true, isDel: true, isTab: true, isEdit: true}:undefined"
               :edit-config="{trigger: 'dblclick', mode: 'cell'}">
      <vxe-table-column v-if="editable"
                        type="index"
                        width="40"
                        align="center"></vxe-table-column>
      <template v-for="(col,idx) in columns">
        <vxe-table-column :key="`col_${idx}`"
                          :field="col.name"
                          :title="col.title"
                          :width="col.width"
                          headerAlign="center"
                          :edit-render="editable?{name: 'Input'}:null">
          <template v-slot="{ row,column }">
            {{row[column.property]}}

            <draggable v-if="showDragMask"
                       v-bind="{group:dragGroup, ghostClass: 'ghost'}"
                       class="dragable-mask"
                       @add="(evt)=>handleDragAdd({evt,row,column})">
            </draggable>

          </template>
        </vxe-table-column>
      </template>
    </vxe-table>
  </div>
</template>
<script>
import draggable from 'vuedraggable'
export default {
  name: 'VucExcel',
  components: { draggable },
  props: {
    showDragMask: {
      type: Boolean,
      default: false
    },
    editable: {
      type: Boolean,
      default: true
    },
    // 表格高度
    height: {
      type: Number,
      default: 250
    },
    // 拖动group名称
    dragGroup: {
      type: String,
      default: 'cell'
    },
    // 配置
    cells: {
      type: Array,
      default: () => []
    },
    // excel表数据
    data: {
      type: Array,
      default: () => []
    },
    border: {
      type: Boolean,
      default: true
    }
  },
  data () {
    return {
      prefixCls: 'vuc-excel',
      tableData: [],
      columns: [],
      // 列数
      colCount: 5,
      // 行数
      rowCount: 5,
      // 单元格合并
      cellList: [],
      bgColor: '#fff',
      fontColor: '#888',
      // 缩进
      textIndent: 0,
      // 字体大小
      fontSize: '14px',
      fontList: ['12px', '14px', '16px', '18px', '20px', '22px', '24px', '32px', '36px'],
      startColIndex: this.editable ? 0 : 1
    }
  },
  watch: {
    cells: {
      deep: true,
      handler () {
        this.initExcel()
      }
    }
  },
  methods: {
    initExcel () {
      // console.log(this.cells)
      this.rowCount = this.cells.length || 5
      this.colCount = (this.cells && this.cells.length > 0) ? this.cells[0].length : 5
      /// //
      this.tableData = []
      this.columns = []
      let colList = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'].splice(0, this.colCount)
      // colList = ['A', 'B', 'C', 'E', 'F']
      colList.forEach((col, idx) => {
        this.columns.push({ name: col, title: col, width: 100 })
      })
      this.cellList = []
      for (let i = 0; i < this.rowCount; i++) {
        this.tableData.push({ A: '' })
        let rowCellist = []
        for (let j = 0; j < this.columns.length; j++) {
          if (j === 0) {
            rowCellist = []
          }
          rowCellist.push({ rowspan: 1, colspan: 1, style: {}, class: '' })
        }
        this.cellList.push(rowCellist)
      }
      if (this.data && this.data.length > 0) {
        this.tableData = [...this.data]
      }
      if (this.cells.length > 0) {
        this.cellList = [...this.cells]
      }
    },
    /// ///////////////////
    async getRanges () {
      const { rows, columns, rowNodes } = this.$refs.vucExcel.getMouseCheckeds()
      let startRow = 9999
      let targetRow = -1
      let startCol = 9999
      let targetCol = -1
      for (let i = 0, len = rowNodes.length; i < len; i++) {
        const list = rowNodes[i]
        if (list.length > 0) {
          const tr = list[0].parentNode
          const rowIndex = parseInt(tr.getAttribute('data-rowid').replace('row_', '')) - 1
          if (rowIndex < startRow) {
            startRow = rowIndex
          }
          if (rowIndex > targetRow) {
            targetRow = rowIndex
          }
          /// /
          for (let j = 0; j < list.length; j++) {
            const td = list[j]
            const colIndex = parseInt(td.getAttribute('data-colid').replace('col_', '')) - 1
            const colspan = parseInt(td.getAttribute('colspan'))
            const rowspan = parseInt(td.getAttribute('rowspan'))
            if (colIndex < startCol) {
              startCol = colIndex
            }
            if (colIndex > targetCol) {
              targetCol = colIndex
            }
            if (targetCol < (colIndex + colspan - 1)) {
              targetCol = colIndex + colspan - 1
            }
            if (targetRow < (rowIndex + rowspan - 1)) {
              targetRow = rowIndex + rowspan - 1
            }
          }
        }
      }

      return { rows, columns, rowNodes, startRow, targetRow, startCol, targetCol }
    },
    // 合并
    async mergeCell () {
      const { startRow, targetRow, startCol, targetCol } = await this.getRanges()
      let icell = 0

      for (let irow = startRow; irow <= targetRow; irow++) {
        for (let icol = startCol; icol <= targetCol; icol++) {
          if (icell === 0) {
            this.cellList[irow][icol - 1] = Object.assign(this.cellList[irow][icol - 1], { rowspan: targetRow - startRow + 1, colspan: targetCol - startCol + 1 })
          } else {
            this.cellList[irow][icol - 1] = Object.assign(this.cellList[irow][icol - 1], { rowspan: 0, colspan: 0 })
          }
          icell = icell + 1
        }
      }
      this.$refs.vucExcel.clearAll()
      this.$refs.vucExcel.updateData()
    },
    async splitCell (rowIndex, colIndex) {
      const cell = this.cellList[rowIndex][colIndex]
      const rowspan = cell.rowspan
      const colspan = cell.colspan
      for (let i = 0; i < rowspan; i++) {
        for (let j = 0; j < colspan; j++) {
          this.cellList[rowIndex + i][colIndex + j] = Object.assign(this.cellList[rowIndex + i][colIndex + j], { rowspan: 1, colspan: 1 })
        }
      }
    },
    // 拆分
    async splitCells () {
      const { startRow, targetRow, startCol, targetCol } = await this.getRanges()
      for (let irow = startRow; irow <= targetRow; irow++) {
        for (let icol = startCol; icol <= targetCol; icol++) {
          this.splitCell(irow, icol - 1)
        }
      }
      this.$refs.vucExcel.clearAll()
      this.$refs.vucExcel.updateData()
    },
    unbordered () {
      this.bordered(true)
    },
    async bordered (noBorder) {
      const { startRow, targetRow, startCol, targetCol } = await this.getRanges()
      let iposRow = 0
      let iposCol = 0
      for (let irow = startRow; irow <= targetRow; irow++) {
        iposCol = 0
        for (let icol = startCol; icol <= targetCol; icol++) {
          if (iposRow === 0) {
            if (irow === 0) {
              if (this.cellList[irow][icol - 1]) {
                this.cellList[irow][icol - 1].style['border-top'] = noBorder ? '' : '1px #888 solid'
              }
            } else {
              if (this.cellList[irow - 1][icol - 1]) {
                this.cellList[irow - 1][icol - 1].style['border-bottom'] = noBorder ? '' : '1px #888 solid'
              }
            }
          }
          /// //
          if (iposCol === 0) {
            if (icol === 1) {
              if (this.cellList[irow][icol - 1]) {
                this.cellList[irow][icol - 1].style['border-left'] = noBorder ? '' : '1px #888 solid'
              }
            } else {
              if (this.cellList[irow][icol - 2]) {
                this.cellList[irow][icol - 2].style['border-right'] = noBorder ? '' : '1px #888 solid'
              }
            }
          }
          if (this.cellList[irow][icol - 1]) {
            this.cellList[irow][icol - 1].style['border-right'] = noBorder ? '' : '1px #888 solid'
            this.cellList[irow][icol - 1].style['border-bottom'] = noBorder ? '' : '1px #888 solid'
          }
          iposCol++
        }
        iposRow++
      }
      this.$refs.vucExcel.clearAll()
      this.$refs.vucExcel.updateData()
    },
    async handleColorChange (styleName) {
      setTimeout(async () => {
        const { startRow, targetRow, startCol, targetCol } = await this.getRanges()
        for (let irow = startRow; irow <= targetRow; irow++) {
          for (let icol = startCol; icol <= targetCol; icol++) {
            this.cellList[irow][icol - 1].style[styleName] = styleName === 'color' ? this.fontColor : this.bgColor
          }
        }
        // this.$refs.vucExcel.clearAll()
        this.$refs.vucExcel.updateData()
      }, 30)
    },
    /// /////////////
    async setAlign (align) {
      const { startRow, targetRow, startCol, targetCol } = await this.getRanges()
      for (let irow = startRow; irow <= targetRow; irow++) {
        for (let icol = startCol; icol <= targetCol; icol++) {
          this.cellList[irow][icol - 1].class = `col--${align}`
        }
      }
      this.$refs.vucExcel.updateData()
    },
    /// ////////////
    async setIndent (step) {
      if (this.textIndent === 0 && step < 0) {
        return false
      }
      this.textIndent = this.textIndent + step
      if (this.textIndent < 0) {
        this.textIndent = 0
      }
      const { startRow, targetRow, startCol, targetCol } = await this.getRanges()
      for (let irow = startRow; irow <= targetRow; irow++) {
        for (let icol = startCol; icol <= targetCol; icol++) {
          this.cellList[irow][icol - 1].style['text-indent'] = `${this.textIndent}px`
        }
      }
      this.$refs.vucExcel.updateData()
    },
    async handleFontSizeChange (val) {
      /*       this.fontSize = val
            console.log(this.fontSize) */
      const { startRow, targetRow, startCol, targetCol } = await this.getRanges()
      for (let irow = startRow; irow <= targetRow; irow++) {
        for (let icol = startCol; icol <= targetCol; icol++) {
          this.cellList[irow][icol - 1].style['font-size'] = `${this.fontSize}`
        }
      }
      this.$refs.vucExcel.updateData()
    },
    /// ////////////////////
    rowspanMethod ({ row, $rowIndex, $columnIndex, column, data }) {
      return this.cellList[$rowIndex][this.startColIndex + $columnIndex - 1]
    },
    cellStyle ({ row, rowIndex, column, columnIndex }) {
      // console.log(this.cellList, rowIndex, columnIndex)
      let cell = this.cellList[rowIndex][this.startColIndex + columnIndex - 1]
      if (cell) {
        return cell.style
      }
      // return this.cellList[rowIndex][columnIndex].cellStyle
    },
    cellClassName ({ row, rowIndex, column, columnIndex }) {
      let cell = this.cellList[rowIndex][this.startColIndex + columnIndex - 1]
      if (cell) {
        return cell.class
      }
    },
    headerCellStyle ({ column, columnIndex }) {
      // return 'border:1px red solid;'
    },
    /// /////////////////////////
    handleDragAdd ({ evt, row, column }) {
      // this.dragList.push(this.dragItem)
      this.$emit('on-drag-add', { evt, row, column })
    },
    // ///////////
    async getExcelCells () {
      const data = this.$refs.vucExcel.getTableData().fullData
      return { cells: this.cellList, data }
    }

  },
  created () {
    this.initExcel()
  }
}
</script>
<style lang="less">
@import './vuc-excel.less';
</style>
