<template>
  <div class="table-wrapper">
    <template v-if="config.data.length">
      <table
        width="auto"
        border="0"
        class="table"
        :style="disabled ? 'width:100%' : ''"
      >
        <thead>
          <tr>
            <!-- 行头 -->
            <th class="th-tg sm"></th>

            <!-- 列头 -->
            <th
              v-for="(item, index) in columnHeader"
              :key="index"
              class="th-tg th-col"
              :data-cindex="item"
              :data-rindex="-1"
              @contextmenu.prevent="rightClickHandle"
            >
              {{ item }}
            </th>
          </tr>
        </thead>

        <tbody>
          <tr v-for="(row, index) in config.data" :key="index">
            <!-- 行头 -->
            <th
              class="th-tg th-row sm"
              @contextmenu.prevent="rightClickHandle"
              :data-rindex="rowHeader[index]"
              :data-cindex="-1"
            >
              {{ rowHeader[index] }}
            </th>

            <td
              v-for="(cell, cell_index) in row"
              :key="`${index}_${cell_index}`"
              :data-rindex="rowHeader[index]"
              :data-cindex="columnHeader[cell_index]"
              :data-key="cell.Uid"
              @click="clickCell($event, cell)"
              @contextmenu.prevent="rightClickHandle($event,cell)"
            >
              <span
                :data-rindex="rowHeader[index]"
                :data-cindex="columnHeader[cell_index]"
                :data-key="cell.Uid"
                v-if="cell.DataType === 4 || disabled"
              >
                {{ cell.ShowValue }}</span
              >

              <el-autocomplete
                v-else
                v-model="cell.ShowValue"
                :fetch-suggestions="searchTarget"
                popper-class="edb-select-popover"
                :data-key="cell.Uid"
                :data-rindex="rowHeader[index]"
                :data-cindex="columnHeader[cell_index]"
                @select="selectTarget($event,cell)"
                @click="clickCell($event, cell)"
                @change.native="changeVal($event, cell)"
              >
                <template slot-scope="scope">
                    <edbDetailPopover :info="scope.item">
                      <div slot="reference">
                          {{ scope.item.EdbName }}
                      </div>
                    </edbDetailPopover>
                </template>
              </el-autocomplete>
            </td>
          </tr>
        </tbody>
      </table>

      <!-- 右键菜单 -->
      <div class="contextMenu-wrapper" id="contextMenu-wrapper" @mouseleave="hideContextMenu">
        <div class="item" v-for="menu in config.contextMenuOption" :key="menu.key" @click="handleContext(menu.key)">{{menu.label}}</div>
      </div>
    </template>

    <div class="nodata" v-else>
      <tableNoData text="暂无数据"/>
    </div>
  </div>
</template>
<script>
import {
  getRowHeaderCode,
  getColumnHeaderCode,
  selectCellStyle,
  selectMoreCellStyle,
  setRelationStyle,
  getRightClickMenu,
  checkDateFormat,
  setFocus,
  findCellByKey
  
} from "../common/customTable";
import * as sheetInterface from "@/api/modules/sheetApi.js";
import md5 from '@/utils/md5.js'
export default {
  props: {
    disabled: { //是否只预览
      type: Boolean,
      default: false
    }
  },
  computed: {
    //列头
    columnHeader() {
      return getColumnHeaderCode(
        this.config.data[0] ? this.config.data[0].length : 0
      );
    },
    //行头
    rowHeader() {
      let total_length = this.config.data.length;
      // console.log(this.config.data)
      return getRowHeaderCode(total_length);
    },
  },
  data() {
    return {
      config: {
        data: [],
        contextMenuOption: [],
      },

      selectCell: {},

      rightClickCell: {},

      insertRelationArr: []
    };
  },
  mounted() {
    if(this.$route.path === '/addMixedSheet' && !this.$route.query.id) this.initData();
  },
  methods: {

    async searchTarget(query,cb) {
      if(!query) return cb([])
      // cb([])
      
      const res = await sheetInterface.searchTarget({
        KeyWord: query,
        CurrentIndex: 1,
        PageSize: 1000
      })
      if(res.Ret !== 200) return

      cb(res.Data.List)
    },

    /* 单击 */
    clickCell(e, cell) {
      if(this.disabled) return

      selectCellStyle(e);
      this.selectCell = cell;
      
      setFocus(e);

      //插入值时寻找关联依赖的单元格 设置选框
      if(cell.DataType === 4) {
        const { key } = e.target.dataset;
        if(!this.insertRelationArr.find(_ => _.key===key)) return
        let { relation_date,relation_edb } = this.insertRelationArr.find(_ => _.key===key)

        setRelationStyle(relation_date)
        setRelationStyle(relation_edb)
      }
    },

    /* 插入值 往左往上寻找同行同列是否有符合条件的一指标一日期 */
    async insertValue() {
      
      let params = this.findNearestCell();
      console.log(params)
      if(!params) {
        this.selectCell.DataType = 3;
        this.selectCell.ShowValue = '';
        this.selectCell.Value = '';
        this.selectCell.DataTime = '';
        this.selectCell.EdbInfoId = 0;
        this.$message.warning('无法在此处插入值');
        return
      }

      const { EdbInfoId,Date } = params

      const res = await sheetInterface.insertData({EdbInfoId,Date})
      if(res.Ret !==200) return

      if(!res.Data){
        this.selectCell.DataType = 3;
        this.selectCell.ShowValue = '';
        this.selectCell.Value = '';
        this.selectCell.DataTime = '';
        this.selectCell.EdbInfoId = 0;
        this.$message.warning('所选指标的所选日期无值')
        return
      }

      this.$message.success('插入成功')

      this.selectCell.DataType = 4;
      this.selectCell.ShowValue = res.Data;
      this.selectCell.Value = res.Data;
      this.selectCell.EdbInfoId = EdbInfoId;
      this.selectCell.DataTime = Date;

      this.setRelation(params)
    },
    
    // 建立插入单元格和依赖单元格关联关系
    setRelation(data) {
      const { insert_cell } = data;
      let relation_obj = {
        type: 4,
        key: insert_cell.key,
        relation_date: {
          type: 1,
          key: insert_cell.relation_date
        },
        relation_edb: {
          type: 2,
          key: insert_cell.relation_edb
        }
      }

      let haveIndex = this.insertRelationArr.findIndex(_ => _.key===insert_cell.key);
      if(haveIndex===-1) {
        this.insertRelationArr.push(relation_obj)
      }else {
        this.insertRelationArr.splice(haveIndex,1,relation_obj)
      }
      console.log(this.insertRelationArr)
    },

    /* 向左向上找出所有格子 找出离插入单元格最近的两个符合条件的单元格 看是否满足一指标一日期的条件
      不满足就无法插入值
    */
    findNearestCell() {
      let { rindex,cindex,key } = this.rightClickCell;
      
      let index_row = this.rowHeader.findIndex(_ => _===rindex);
      let index_col = this.columnHeader.findIndex(_ => _===cindex);

      //同行左侧所有格子
      let row_cell_arr = this.config.data[index_row].filter((_,cell_index) => cell_index<index_col);
      //同列上侧所有格子
      let col_cell_arr = this.config.data.filter((row,row_index) => row_index<index_row).map(row=> row[index_col]);

      if(!row_cell_arr.length || !col_cell_arr.length){
        return null
      }

      //寻找最近的符合1 2类型的两个格子
      let params = null;
      
      for (let i = row_cell_arr.length - 1; i >= 0; i--) {
        for (let j = col_cell_arr.length - 1; j >= 0; j--) {
          if(!params) {
            if((row_cell_arr[i].DataType===1&&col_cell_arr[j].DataType===2)
            ||(row_cell_arr[i].DataType===2&&col_cell_arr[j].DataType===1)) {
              params = {
                Date: row_cell_arr[i].DataType===1 ? row_cell_arr[i].ShowValue : col_cell_arr[j].ShowValue,
                EdbInfoId: row_cell_arr[i].DataType===2 ? row_cell_arr[i].EdbInfoId : col_cell_arr[j].EdbInfoId,
                insert_cell: {
                  key,
                  relation_date: row_cell_arr[i].DataType===1 ? row_cell_arr[i].Uid: col_cell_arr[j].Uid,
                  relation_edb: row_cell_arr[i].DataType===2 ? row_cell_arr[i].Uid: col_cell_arr[j].Uid,
                },
              }
              break
            }
          }
        }
      }
      return params;

    },

    /* 选择指标 单元格类型为2*/
    selectTarget(e,cell) {
      const { EdbName,EdbInfoId }  = e;

      cell.DataType = 2;
      cell.DataTime = '';
      cell.ShowValue = EdbName;
      cell.Value = EdbName;
      cell.EdbInfoId = EdbInfoId;


      this.checkCellRelation(e,cell)
    },

    /* 输入框失焦  */
    async changeVal(e, cell) {
      // 是日期格式 DataType为1
      //是指标 DataType为2
      // 否则是3

      const {value} = e.target;
      if(!value){ //无值重置单元格
        cell.DataType = 3;
        cell.ShowValue = value;
        cell.Value = value;
        cell.EdbInfoId = 0;
        cell.DataTime = '';
      }else {
        console.log(checkDateFormat(value))
        if(checkDateFormat(value)) { //是日期格式
          cell.DataType = 1;
          
          cell.ShowValue = checkDateFormat(value);
          cell.Value = checkDateFormat(value);
        }else if(cell.EdbInfoId&&!cell.DataTime&&cell.Value===value) {//指标
  
        }else {//自定义值
          cell.DataType = 3;
          cell.ShowValue = value;
          cell.Value = value;
          cell.EdbInfoId = 0;
          cell.DataTime = '';
        }
      }

      //判断是否是有插入值的依赖单元格 更新值或重置关系
      this.checkCellRelation(e,cell)
    },

    /* 当前单元格是否和插入值有关联 无就不管 */
    async checkCellRelation(e,cell) {
      if(!this.insertRelationArr.length) return

      const key= cell.Uid;
      
      //有关联的N组数组
      let haveRelationArr = this.insertRelationArr.filter(_ => _.relation_date.key===key||_.relation_edb.key===key);

      if(!haveRelationArr.length) return

      //去处理每一组关联的情况
      haveRelationArr.forEach( async(relation) => {
        const { relation_date,relation_edb } = relation;
  
        if((relation_date.key === key && cell.DataType === 1) || (relation_edb.key === key && cell.DataType === 2)) { //单元格类型不变只变值仍有关联关系 更新值
  
          //刷新插入值结果
          let params = null;
          if(relation_date.key === key && cell.DataType === 1) { //修改的是依赖日期格
            let { EdbInfoId } = findCellByKey(this.config.data,relation_edb.key)
            params = {
              EdbInfoId,
              Date: cell.ShowValue
            }
  
          } else if( relation_edb.key === key && cell.DataType === 2) { //修改的依赖指标格
            let {ShowValue} = findCellByKey(this.config.data,relation_date.key)
            params = {
              EdbInfoId: cell.EdbInfoId,
              Date: ShowValue
            }
          }
  
          const res = await sheetInterface.insertData(params)
          if(res.Ret !==200) return

          !res.Data && this.updateInsertCell(relation.key,true);
  
          res.Data && this.config.data.forEach(row => {
            row.forEach(cell => {
              if(cell.Uid === relation.key) {
                  cell.DataType = 4;
                  cell.ShowValue = res.Data;
                  cell.Value = res.Data;
                  cell.EdbInfoId = params.EdbInfoId;
                  cell.DataTime = params.Date;
              }
            })
          })
  
        }else {
          // 清除插入值单元格式和关联关系
          this.updateInsertCell(relation.key);
        }
      })
 
    },

    // 清除插入值单元格式和关联关系
    updateInsertCell(key,initValue=false) {
      this.config.data.forEach(row => {
        row.forEach(cell => {
          if(cell.Uid === key) {
            cell.DataType = 3;
            cell.EdbInfoId = 0;
            cell.DataTime = '';
            if(initValue) {
                cell.ShowValue = '';
                cell.Value = '';
            }
          }
        })
      })

      let relationIndex = this.insertRelationArr.findIndex(_ => _.key===key)
      this.insertRelationArr.splice(relationIndex,1)
    },

    /* 右键 */
    rightClickHandle(e,cell) {
      if(this.disabled) return

      const { rindex,cindex,key } = e.target.dataset;
      this.rightClickCell = {
        rindex,
        cindex,
        key
      }

      this.selectCell = cell;

      let pos;
      if(rindex==='-1') { //列头处
        pos = 'col'
      }else if(cindex==='-1') { //行头
        pos = 'row'
      }else {//单元格
        pos = 'cell'
      }
      this.config.contextMenuOption = getRightClickMenu(pos)


      const dom = $('#contextMenu-wrapper')[0];
			dom.style.left = e.clientX-3 + 'px';
			dom.style.top = e.clientY-3 + 'px';
      
      ['col','row'].includes(pos) && selectMoreCellStyle(e);
      pos==='cell' && this.clickCell(e,cell);
    },

    /*  */
    hideContextMenu() {
      const dom = $('#contextMenu-wrapper')[0];
			dom.style.left = '-9999px';
			dom.style.top = '-9999px';
    },

    /* 右键事件 */
    async handleContext(key) {
      const keyMap = {
        'del': this.delColOrRow,
        'insert-col-left': this.insertCol,
        'insert-col-right': this.insertCol,
        'insert-row-up': this.insertRow,
        'insert-row-down': this.insertRow,
        'insert-value': this.insertValue
      }
      keyMap[key] && keyMap[key](key)
      this.hideContextMenu()
    },

    /* 删除行列 */
    delColOrRow() {
      let { rindex,cindex } = this.rightClickCell;

      if(rindex==='-1') { //删除列
        console.log('删除列',cindex)

        if(this.columnHeader.length === 1) return this.$message.warning('请至少保留一列')

        let index = this.columnHeader.findIndex(_ => _ === cindex);

        //删除时清除关系
        if(this.insertRelationArr.length) {
          let delCellIds = this.config.data.map(row => row[index].Uid);
          this.insertRelationArr = this.insertRelationArr.filter(_ => !delCellIds.includes(_.key)&&!delCellIds.includes(_.relation_date.key)&&!delCellIds.includes(_.relation_edb.key))
        }

        this.config.data.forEach(row => {
          row.splice(index,1)
        })
      }else if(cindex === '-1') { //删除行
        console.log('删除行',rindex)

        if(this.rowHeader.length === 1) return this.$message.warning('请至少保留一行')

        let index = this.rowHeader.findIndex(_ => _ === rindex)
        
        if(this.insertRelationArr.length) {
          //删除时清除关系
          let delCellIds = this.config.data[index].map(cell => cell.Uid);
          this.insertRelationArr = this.insertRelationArr.filter(_ => !delCellIds.includes(_.key)&&!delCellIds.includes(_.relation_date.key)&&!delCellIds.includes(_.relation_edb.key));
        }

        this.config.data.splice(index,1)

      }
      console.log(this.insertRelationArr)
    },

    /* 插入列 */
    insertCol(key) {
      let { cindex } = this.rightClickCell;
      
      let index = this.columnHeader.findIndex(_ => _ === cindex);

      this.config.data.forEach((row,rindex) => {
        row.splice(key==='insert-col-left'?index:index+1,0,{
          ShowValue: "",
          Value: "",
          DataType: 3,
          DataTime: "",
          EdbInfoId: 0,
          Uid: md5.hex_md5(`${new Date().getTime()}${rindex}`)
        })
      })
      
    },

    /* 插入行 */
    insertRow(key) {
      let { rindex } = this.rightClickCell;
      
      let index = this.rowHeader.findIndex(_ => _ === rindex)

      let row = new Array(this.columnHeader.length).fill("").map((_,cindex) => ({
        ShowValue: "",
        Value: "",
        DataType: 3,
        DataTime: "",
        EdbInfoId: 0,
        Uid: md5.hex_md5(`${new Date().getTime()}${cindex}`)
      }));

      this.config.data.splice( key==='insert-row-up'?index:index+1,0,row)

    },

    /* 初始化8行5列 */
    initData(initData=null) {
      if(initData) {
        const { CellRelation,Data } = initData;
        this.config.data = Data;
        this.insertRelationArr = JSON.parse(CellRelation);
      }else {

        this.config.data = new Array(8).fill("").map((_,_rindex) => {
          return new Array(5).fill("").map((cell,_cindex) => ({
            ShowValue: "",
            Value: "",
            DataType: 3,
            DataTime: "",
            EdbInfoId:0,
            Uid: md5.hex_md5(`${new Date().getTime()}${_rindex}${_cindex}`)
          }));
        });
      }
    },
  },
};
</script>
<style scoped lang="scss">
.nodata {
  text-align: center;
  font-size: 16px;
  color: #666;
  padding: 100px 0;
}
.table-wrapper {
  width: 100%;
  overflow: auto;
  .table td,th {
    width: 104px;
    min-width: 104px;
    height: 35px;
    background: #fff;
    text-align: center;
    word-break: break-all;
    border: 1px solid #dcdfe6;
    overflow: hidden;
    text-overflow: ellipsis;
    position: relative;
    color: #606266;

    &.td-chose::after {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      content: "";
      display: block;
      outline: 0;
      border: 2px solid #0033ff;
      box-shadow: 0 0 5px rgba(73, 177, 249, 0.5);
    }
    &.td-relation::after {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      content: "";
      display: block;
      outline: 0;
      border: 2px dashed #0033ff;
      box-shadow: 0 0 5px rgba(73, 177, 249, 0.5);
    }
    &.td-col-select::after {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      content: "";
      display: block;
      outline: 0;
      border: 1px solid rgb(24, 173, 24);
      border-bottom: none;
      border-top: none;
    }
    &.td-row-select::after {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      content: "";
      display: block;
      outline: 0;
      border: 1px solid rgb(24, 173, 24);
      border-left: none;
      border-right: none;
    }
    &.insert {
      background: #ffefdd;
    }
  }

  .th-tg {
    background: #ebeef5;
    &:hover {
      cursor: pointer;
      background: #ddd;
      /* border: 2px solid #409eff; */
    }
    &.sm {
      width: 36px;
      min-width: 36px;
      max-width: 36px;
    }
  }
  //整行选中
  tr {
    position: relative;
    &.choose-all::after {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      content: "";
      display: block;
      outline: 0;
      border: 2px solid #5897fb;
      box-shadow: 0 0 5px rgba(73, 177, 249, 0.5);
    }
  }

  .contextMenu-wrapper {
    position: fixed;
    z-index: 99;
    top: -9999px;
    left: -9999px;
    background: #fff;
    padding: 10px 0;
    /* border: 1px solid #999; */
    box-shadow: 0 1px 4px #999;
    .item {
      padding: 10px 25px;
      cursor: pointer;
      &:hover {
        background-color: #f5f7fa;
      }
    }
  }
}
</style>
<style lang="scss">
.table-wrapper {
  td {
    .el-input__inner {
      border: none;
      outline: none;
      text-align: center;
      height: 34px;
      line-height: 34px;
    }
  }
  .el-input.is-disabled .el-input__inner {
    background-color: #fff;
  }
}
.edb-select-popover {
  width: 300px !important;
}
</style>
