<template>
  <table class="content-table" ref="tableRef">
    <tr class="header">
      <th v-for="(col, i) in rows[0]">列 {{ i + 1 }}</th>
      <th>删除</th>
    </tr>
    <tr v-for="(row, rowIndex) in rows" class="row" :key="rowIndex">
      <td
        v-for="(col, colIndex) in row"
        class="col"
        :key="colIndex"
        @click="inputPos = [rowIndex, colIndex]"
      >
        <input
          :ref="(dom: any) => inputRef = dom"
          @blur="inputPos = null"
          v-if="inputPos && rowIndex === inputPos[0] && colIndex === inputPos[1]"
          :value="col"
          @change="ev => setColValue(rowIndex, colIndex, (ev.target as any).value)"
        />
        <span v-else>{{ col }}</span>
      </td>
      <td>
        <el-button type="primary" plain size="small" @click="delRow(rowIndex)">
          <el-icon><Minus /></el-icon>
        </el-button>
      </td>
    </tr>
  </table>
  <div class="add-row-layout">
    <el-button type="primary" @click="addRow">
      <el-icon><Plus /></el-icon> 行
    </el-button>
  </div>
</template>

<script setup lang="ts">
import { ElMessage } from "element-plus";
import { computed, ref, watchEffect } from "vue";
import { QuiskExpose } from "@/helper/mount";

export type EshapeTableContent = {
  width: number;
  height: number;
  value: string;
  colIndex: number;
  rowIndex: number;
}[];

const props = defineProps<{ content: EshapeTableContent; track?: boolean }>();
const bindContent = ref(props.content.map((item) => ({ ...item })));
const inputPos = ref<[number, number] | null>(null);
const inputRef = ref<HTMLInputElement>();

watchEffect(
  () => {
    if (inputRef.value) {
      inputRef.value.focus();
    }
  },
  { flush: "post" }
);

const delRow = (rowIndex: number) => {
  if (rows.value.length === 1) {
    ElMessage.error("表格最少需要保留一行！");
  } else {
    bindContent.value = bindContent.value
      .filter((item) => item.rowIndex !== rowIndex)
      .map((item) => {
        if (item.rowIndex > rowIndex) {
          return { ...item, rowIndex: item.rowIndex - 1 };
        } else {
          return item;
        }
      });
  }
};

const addRow = () => {
  const colSize = rows.value[0].length;
  const rowSize = rows.value.length;
  for (let i = 0; i < colSize; i++) {
    bindContent.value.push({
      width: 0,
      height: 0,
      colIndex: i,
      rowIndex: rowSize,
      value: "",
    });
  }
};

const setColValue = (rowIndex: number, colIndex: number, val: string) => {
  const item = bindContent.value.find(
    (item) => item.rowIndex === rowIndex && item.colIndex === colIndex
  )!;
  item.value = val;
};

const rows = computed(() => {
  const rows: string[][] = [];
  bindContent.value.forEach((item) => {
    rows[item.rowIndex] = rows[item.rowIndex] || [];
    rows[item.rowIndex][item.colIndex] = item.value;
  });
  return rows;
});

const tableRef = ref<HTMLTableElement>();
defineExpose<QuiskExpose>({
  submit() {
    const dom = tableRef.value!;
    const rows = Array.from(dom.querySelectorAll(".row"));
    for (let i = 0; i < rows.length; i++) {
      const cols = Array.from(rows[i].querySelectorAll(".col"));

      for (let j = 0; j < cols.length; j++) {
        const col = cols[j] as HTMLElement;
        const item = bindContent.value.find(
          (item) => item.rowIndex === i && item.colIndex === j
        )!;
        item.width = col.offsetWidth;
        item.height = col.offsetHeight;
      }
    }
    return bindContent.value;
  },
});
</script>

<style lang="scss" scoped>
.content-table {
  width: 100%;
  height: 100%;
  border-collapse: collapse;
  --border-color: #f0f2f5;
  margin-bottom: 10px;

  th {
    background: #fafafb;
  }

  tr:first-child {
    th,
    td {
      border-top: 1px solid var(--border-color);
    }
  }
  th:first-child,
  td:first-child {
    border-left: 1px solid var(--border-color);
  }
  th,
  td {
    border-right: 1px solid var(--border-color);
    border-bottom: 1px solid var(--border-color);
    text-align: center;
  }

  .col:nth-child(1) {
    width: 90px;
  }
  .col:nth-child(2) {
    width: 170px;
  }

  .col {
    cursor: pointer;

    &:hover {
      background-color: rgba(133, 194, 255, 0.1);
    }
    span,
    input {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      font-size: 12px;
      width: 100%;
      height: 100%;
      border: none;
      text-align: center;
      line-height: 24px;
    }
  }
  .col:hover {
    background-color: rgba(133, 194, 255, 0.1);
  }
}

.add-row-layout {
  text-align: center;
}
</style>
