<!-- 搜索表单 -->
<template>
  <div style="margin-top: 10px">
    <div v-if="isSelecting" class="selection-box" :style="selectionStyle"></div>
    <el-button type="primary" @click="addColumn()" v-if="edit"
      >新增列</el-button
    >
    <el-button type="primary" @click="addRow(columns[0].length)" v-if="edit"
      >新增行</el-button
    >
    <el-checkbox v-model="isMerge" style="margin-left: 10px" v-if="edit"
      >合并单元格</el-checkbox
    >
    <div class="table" style="margin-top: 10px" :id="id">
      <div
        class="table-body"
        style="display: flex"
        @mousedown="startSelecting"
        @mousemove="updateSelection"
        @mouseup="stopSelecting"
      >
        <!-- <el-popover
          style="position: fixed; z-index: 2000"
          width="400"
          ref="popoverRef"
          v-model="rightClickShow"
        >
          <el-card class="box-card">
            <div slot="header" class="clearfix" @click="rightClickShow = false">
              <span>合并单元格</span>
              <i class="el-icon-close" style="float: right; padding: 3px 0"></i>
            </div>
            <div class="text item">
              向前合并：
              <el-input v-model="beforeNum" style="width: 100px" type="number">
              </el-input>
              列
            </div>
            <div class="text item" style="margin-top: 10px">
              向后合并：
              <el-input v-model="laterNum" style="width: 100px" type="number">
              </el-input>
              列
            </div>
            <div>
              <el-button
                style="float: right; margin-bottom: 5px"
                type="primary"
                @click="save"
                >确认</el-button
              >
            </div>
          </el-card>
        </el-popover> -->
        <template v-for="(row, index) in columns">
          <div class="column" :style="{ width: row[0].width + 'px' }">
            <div
              class="table-body-item tableTd"
              v-for="(item, rowIndex) in row"
              :style="{
                height: item.rowspan * 30 + 'px',
                display: item.rowspan ? 'block' : 'none',
                ...item.style,
                width: item.colspan ? getWidth(item) : 0
              }"
              @contextmenu.prevent="onRightClick($event, rowIndex, index)"
            >
              <i
                class="el-icon-delete delete"
                style="display: none"
                @click="removeColumn(item, index)"
                v-if="edit && rowIndex == 0"
              ></i>
              <i
                class="el-icon-circle-plus-outline add"
                style="display: none"
                @click="addColumn(item)"
                v-if="edit && rowIndex == 0"
              ></i>
              <i
                class="el-icon-delete deleteRow"
                @click="removeRow(rowIndex)"
                v-if="edit && rowIndex != 0 && item.style?.border != 'none'"
              ></i>
              <i
                class="el-icon-circle-plus-outline addRow"
                style="display: none"
                @click="addRow(rowIndex, item)"
                v-if="edit && rowIndex != 0 && index != columns.length - 1"
              ></i>
              <textarea
                v-if="item.rowspan > 1"
                v-model="item.value"
                class="templateInput"
                :id="item.id"
                :ref="item.id + 'ref'"
                :readonly="item.readonly == 2 || readonly"
                @click="inputClick(item)"
                @input="calculation"
                autocomplete="off"
                style="resize: none"
              ></textarea>
              <input
                v-else
                v-model="item.value"
                class="templateInput"
                :id="item.id"
                :ref="item.id + 'ref'"
                :readonly="item.readonly == 2 || readonly"
                @click="inputClick(item, rowIndex == 0 ? 'columns' : null)"
                @input="calculation"
                type="text"
                autocomplete="off"
              />
            </div>
          </div>
        </template>
      </div>
    </div>
  </div>
</template>

<script>
  import dictMixins from '@/mixins/dictMixins';
  import { generateRandomString } from '@/utils/util';

  export default {
    props: {},
    mixins: [dictMixins],
    props: {
      id: '',
      edit: {
        default: true,
        type: Boolean
      },
      readonly: {
        default: false,
        type: Boolean
      }
    },
    data() {
      return {
        form: null,
        valueObj: {},
        domId: '',
        rightClickShow: false,
        columns: [],
        units: {},
        equation: {},
        beforeNum: 0,
        laterNum: 0,
        currentRowIndex: 0,
        currentColumnIndex: 0,
        isSelecting: false,
        startX: 0,
        startY: 0,
        endX: 0,
        endY: 0,
        selectedItems: [],
        isMerge: false
      };
    },
    created() {},
    computed: {
      selectionStyle() {
        return {
          position: 'fixed',
          left: `${Math.min(this.startX, this.endX)}px`,
          top: `${Math.min(this.startY, this.endY)}px`,
          width: `${Math.abs(this.endX - this.startX)}px`,
          height: `${Math.abs(this.endY - this.startY)}px`,
          border: '2px dashed black'
        };
      }
    },
    methods: {
      startSelecting(event) {
        if (!this.isMerge) {
          return;
        }
        this.isSelecting = true;
        this.startX = event.clientX;
        this.startY = event.clientY;
        this.endX = this.startX;
        this.endY = this.startY;
      },
      updateSelection(event) {
        if (this.isSelecting) {
          this.endX = event.clientX;
          this.endY = event.clientY;
        }
      },
      stopSelecting() {
        this.isSelecting = false;
        // 在这里处理框选结果，例如计算被框选的元素
        this.calculateSelectedItems();
      },
      calculateSelectedItems() {
        this.selectedItems = [];
        this.columns.forEach((cell, columnIndex) => {
          cell.forEach((row, rowIndex) => {
            const rect = this.$refs[row.id + 'ref'][0].getBoundingClientRect();
            if (
              rect.left < this.endX &&
              rect.right > this.startX &&
              rect.top < this.endY &&
              rect.bottom > this.startY
            ) {
              row.columnIndex = columnIndex;
              row.rowIndex = rowIndex;
              this.selectedItems.push(row);
            }
          });
        });
        // console.log(this.selectedItems, 'this.selectedItems[0]');
        // return

        if (this.selectedItems.length < 1) {
          return;
        }
        let _columnIndex = this.selectedItems[0].columnIndex;
        let _rowIndex = this.selectedItems[0].rowIndex;
        let _colspan = this.selectedItems[0].colspan;
        let rowspan = this.selectedItems
          .filter((item) => item.columnIndex === _columnIndex)
          .reduce((acc, cur) => acc + cur.rowspan, 0);
        if (this.verify(_colspan, rowspan, this.selectedItems, _rowIndex)) {
          return;
        }
        console.log(this.selectedItems, 'this.selectedItems');
        for (let index = 0; index < this.selectedItems.length; index++) {
          let item = this.selectedItems[index];
          if (index != 0) {
            if (!this.selectedItems[0].style) {
              this.selectedItems[0].style = {};
            }
            if (
              this.selectedItems[0].rowIndex == item.rowIndex &&
              this.selectedItems[0].columnIndex != item.columnIndex
            ) {
              this.selectedItems[0].colspan += item.colspan;
              this.selectedItems[0].colspanKey.push(item.id);
              this.selectedItems[0].colspanKey.push(...item.colspanKey);
            }
            if (
              this.selectedItems[0].rowIndex != item.rowIndex &&
              this.selectedItems[0].columnIndex == item.columnIndex
            ) {
              this.selectedItems[0].rowspan += item.rowspan;
              item.rowspan = 0;
            }

            item.colspan = 0;
            if (item.style) {
              item.style.border = 'none';
            } else {
              item.style = {
                width: 100,
                border: 'none'
              };
            }

            this.$set(this.columns[item.columnIndex], item.rowIndex, item);
          }
        }
        console.log(this.selectedItems[0], 'this.selectedItems[0]');
        this.$set(this.columns[_columnIndex], _rowIndex, this.selectedItems[0]);
      },
      colspanSum(rowIndex) {
        return this.selectedItems.filter((item) => item.rowIndex == rowIndex);
      },
      verify(_colspan, _rowspan, arr, _rowIndex) {
        for (let index = 0; index < arr.length; index++) {
          let item = arr[index];
          if (_rowIndex === 0 && _rowIndex != item.rowIndex) {
            //表头不能和其他行合并
            return true;
          }
          if (
            item.rowIndex != this.selectedItems[0].rowIndex &&
            _colspan > this.colspanSum(item.rowIndex).length &&
            item.colspan != 0
          ) {
            return true;
          }

          if (item.rowspan > _rowspan) {
            return true;
          }
        }
      },

      // 方法：添加新列
      addColumn(item) {
        let length = this.columns[0]?.length || 1;
        if (item) {
          let _columnIndex = item.columnIndex;
          if (item.colspan > 1) {
            _columnIndex += Number(item.colspan - 1);
          }
          this.columns.splice(
            _columnIndex + 1,
            0,
            Array(length)
              .fill(null)
              .map(() => this.getInput())
          );
        } else {
          this.columns.push(
            Array(length)
              .fill(null)
              .map(() => this.getInput())
          );
        }
      },
      getInput(width) {
        return {
          readonly: 1,
          value: '',
          rowspan: 1,
          colspan: 1,
          colspanKey: [],
          width: width||100,
          style: { width: width||100 },
          id: generateRandomString(5)
        };
      },
      getIndex(id) {
        let columnIndex, rowIndex;
        console.log(id);
        this.columns.forEach((cell, _columnIndex) => {
          let cellIndex = cell.findIndex((data) => data.id == id);
          if (cellIndex != '-1') {
            columnIndex = _columnIndex;
            rowIndex = cellIndex;
          }
        });
        return { columnIndex, rowIndex };
      },

      // 方法：删除指定列
      removeColumn(item, index) {
        this.columns[index].forEach((cell, rowIndex) => {
          if (cell.colspanKey.length) {
            //当前删除的列其他行有合并过单元格的处理
            let data = this.columns[index + 1][rowIndex];

            data.colspan = cell.colspan - 1;
            data.rowspan = cell.rowspan;
            data.style = cell.style;
            data.colspanKey = cell.colspanKey.filter((item) => item != data.id);
            if (data.rowspan > 1) {
              for (let j = 1; j < data.rowspan; j++) {
                this.$set(this.columns[index + 1][rowIndex + j], 'rowspan', 0);
              }
            }
            this.$set(this.columns[index + 1], rowIndex, data);
          }
        });
        if (item?.colspanKey.length) {
          item.colspanKey.forEach((id) => {
            let { columnIndex } = this.getIndex(id);
            console.log(columnIndex, 'columnIndex');

            this.columns[columnIndex].forEach((cell, rowIndex) => {
              if (cell.colspanKey.length) {
                //当前删除的列其他行有合并过单元格的处理
                let data = this.columns[columnIndex + 1][rowIndex];

                data.colspan = cell.colspan - 1;
                data.rowspan = cell.rowspan;
                data.style = cell.style;
                data.colspanKey = cell.colspanKey.filter(
                  (item) => item != data.id
                );
                if (data.rowspan > 1) {
                  for (let j = 1; j < data.rowspan; j++) {
                    this.$set(
                      this.columns[columnIndex + 1][rowIndex + j],
                      'rowspan',
                      0
                    );
                  }
                }
                this.$set(this.columns[columnIndex + 1], rowIndex, data);
              }
            });

            this.columns.splice(index + 1, 1);
          });
        }
        this.columns.splice(index, 1);
        //当前删除的列合并过单元格的列都删除
      },

      // 方法：添加新行
      addRow(rowIndex, row) {
        let _rowIndex = rowIndex;

        if (row?.rowspan > 1) {
          _rowIndex += Number(row?.rowspan - 1);
        }

        this.columns.forEach((item, index) => {

          this.columns[index].splice(_rowIndex + 1, 0, this.getInput(this.columns[index][_rowIndex-1]?.style.width));
        });

        // }
      },
      //找到真正需要改变rowspan的行
      getPreventRowspan(columnIndex, rowIndex) {
        let preventRowspan = null;
        this.columns[columnIndex].forEach((item, newRowIndex) => {
          if (newRowIndex < rowIndex && item.rowspan > 1) {
            //向上找到当前列合并过单元格的行
            preventRowspan = newRowIndex;
          }
        });

        return preventRowspan;
      },
      // 方法：删除指定行
      removeRow(rowIndex) {
        this.columns.forEach((item, columnIndex) => {
          if (item[rowIndex].rowspan == 0) {
            // 如果当前列，删除的这一行rowspan为0，则需要找到真正需要改变rowspan的行
            let preventRowspanIndex = this.getPreventRowspan(
              columnIndex,
              rowIndex
            );
            if (preventRowspanIndex) {
              this.$set(
                this.columns[columnIndex][preventRowspanIndex],
                'rowspan',
                this.columns[columnIndex][preventRowspanIndex].rowspan - 1
              );
            }
          } else if (item[rowIndex].rowspan > 1) {
            //rowspan大于1,代表合并过单元格,需要吧值继承给下一行
            let data = item[rowIndex];
            data.rowspan--;
            this.$set(this.columns[columnIndex], [rowIndex + 1], data);
          }

          item.splice(rowIndex, 1);
        });
      },
      getWidth(item) {
        let width = Number(item.style.width);
        if (item.colspanKey.length) {
          this.columns.forEach((cell) => {
            cell.forEach((row) => {
              if (item.colspanKey.includes(row.id)) {
                width += Number(row.style.width);
              }
            });
          });
        }

        return width + 'px';
      },
      calculation() {
        this.$emit('calculation');
      },
      equationValue({ domId, value }) {
        this.columns.forEach((item, index) => {
          let cellIndex = item.findIndex((cell) => cell.id == domId);
          if (cellIndex != '-1') {
            this.$set(this.columns[index][cellIndex], 'value', value);
          }
        });
      },
      getValue() {
        return {
          form: null,
          equation: this.equation,
          units: this.units,
          valueObj: {
            columns: this.columns
          }
        };
      },
      init({ form, valueObj, equation, units }) {
        this.form = form;
        this.columns = valueObj.columns;
        this.equation = equation || {};
        this.units = units || {};
      },
      editInputChange(domObj) {
        console.log(domObj, 'domObj');
        let data = JSON.parse(JSON.stringify(domObj));
        if (data.equation) {
          this.equation[this.domId] = data.equation;
        }
        if (data.units) {
          this.units[this.domId] = data.units;
        }
        let dom = document.getElementById(data.id);

        this.columns.forEach((item, index) => {
          let rowsIndex = item.findIndex((cells) => cells.id == this.domId);

          if (rowsIndex >= 0) {
            let width = data.width - dom.parentElement.offsetWidth;
            let newWidth = this.columns[index][rowsIndex].style.width + width;
            this.columns[index][0].width = newWidth;
            this.$set(this.columns[index], rowsIndex, data);
            item.forEach((cell, _index) => {
              this.$set(this.columns[index][_index].style, 'width', newWidth);
              this.$set(this.columns[index][_index], 'width', newWidth);
            });
          }
        });
      },
      onRightClick(PointerEvent, rowIndex, columnIndex) {
        this.currentRowIndex = rowIndex;
        this.currentColumnIndex = columnIndex;
        if (rowIndex === 0) {
          this.rightClickShow = true;
          this.$nextTick(() => {
            let y = PointerEvent.pageY;
            let x = PointerEvent.pageX + 10;
            if (PointerEvent.screenY >= PointerEvent.view.innerHeight) {
              y -= 80;
            }
            this.$refs.popoverRef.$el.style.top = y + 'px';
            this.$refs.popoverRef.$el.style.left = x + 'px';
          });
        }
      },

      inputClick(item, type) {
        if (!this.edit) {
          return;
        }
        let dom = document.getElementById(item.id);

        this.domId = item.id;
        this.$emit('editShow', {
          templateDivRef: 'customTextRef' + this.id,
          domObj: {
            ...item,
            width: dom.parentElement.offsetWidth,
            isNoWidth: type != 'columns' ? false : true,
            equation: this.equation[item.id],
            units: this.units[item.id] || {}
          }
        });
      }
    }
  };
</script>
<style lang="scss" scoped>
  :deep(.templateInput) {
    width: 100%;
    height: 100%;
    border: none;

    text-align: center;
    background-color: #fff;
  }

  .table-header {
    span {
      display: inline-block;
      height: 30px;
      border: 1px solid #ddd;
      width: 100px;
      background-color: #f2f2f2 !important;
    }

    input {
      background-color: #f2f2f2 !important;
    }
  }
  .table-body {
    white-space: nowrap;
    .column {
      display: inline-block;
      > div {
        height: 30px;
        border: 1px solid #ddd;
        width: 100%;
      }
      > div:nth-of-type(1) {
        background-color: #f2f2f2 !important;
        > input {
          background-color: #f2f2f2 !important;
        }
      }
    }
  }
  // th,
  // td {
  //   border: 1px solid #ddd;
  //   padding: 2px;
  //   text-align: center;
  //   height: 30px;
  // }
  // th {
  //   background-color: #f2f2f2;
  //   > input {
  //     background-color: #f2f2f2 !important;
  //   }
  // }
  tr:nth-child(even) {
    background-color: #f9f9f9;
  }
  input:focus {
    border-color: #66afe9; /* 改变边框颜色 */
    outline: none; /* 移除默认的轮廓线 */
  }
  .tableTd {
    position: relative;
  }
  .deleteRow {
    display: block !important;
    position: absolute;
    bottom: 0px;
    right: -15px;
    color: #f56c6c;
  }
  .tableTd:hover {
    .delete {
      display: block !important;
      position: absolute;
      right: 0;
      top: 0;
      color: #f56c6c;
    }

    .add {
      display: block !important;
      position: absolute;
      right: 20px;
      top: 0;
      color: #409eff;
    }
    .addRow {
      display: block !important;
      position: absolute;
      bottom: 0px;
      right: 10px;
      color: #409eff;
    }
  }
  .selection-box {
    position: absolute;
    border: 2px dashed black;
    z-index: 999;
    pointer-events: none; /* 确保选择框不会干扰鼠标事件 */
  }
</style>
