<template>
  <div>
    <el-table border :size="size" :data="proxyData" max-height="300px">
      <el-table-column v-for="column in columns" :key="column.prop" v-bind="column" show-overflow-tooltip>
        <template slot-scope="scope">
          <template v-if="column.type === 'index'">{{ scope.$index + 1 }}</template>
          <template v-else-if="column.type === 'image'">
            <div
              v-if="scope.row[column.prop]"
              style="width: 20px; height: 20px"
              class="hover"
              v-viewer
            >
              <img
                :src="scope.row[column.prop]"
                style="display: inline-block; width: 100%; height: 100%"
                alt=""
              />
            </div>
          </template>

          <template v-else-if="column.type === 'select'">
            {{ scope.row[column.select_name] }}
          </template>

          <template v-else>
            {{ scope.row[column.prop] }}
          </template>
        </template>
      </el-table-column>

      <el-table-column label="操作" width="85px" v-if="!readonly">
        <template #header>
          <div class="flex-between">
            <p>操作</p>
            <el-button
              v-if="!readonly"
              style="padding: 0"
              type="text"
              size="mini"
              @click="onInsertData"
              >添加</el-button
            >
          </div>
        </template>

        <template slot-scope="scope">
          <template>
            <el-button type="text" size="mini" style="padding: 0" @click="onCurrentRowDelete(scope.$index)"
              >删除</el-button
            >
            <el-button
              type="text"
              style="padding: 0"
              size="mini"
              @click="onCurrentRowEdit(scope.row, scope.$index)"
              >编辑</el-button
            >
          </template>
        </template>
      </el-table-column>
    </el-table>

    <div class="flex-end" style="margin-top: 10px">
      <slot />
    </div>

    <modal-mode
      :title="title"
      :size="size"
      :rules="rules"
      :index="editIndex"
      :columns="columns"
      :action="action"
      :data="_defaultData"
      :visible.sync="modalVisible"
      @save="onCurrentRowSave"
      @rowUpdate="onRowUpdate"
    />
  </div>
</template>

<script>
import ImageUploadField from "./_image.vue";
import ModalMode from "./_modal.vue";
export default {
  name: "TableEditor",
  components: {
    ImageUploadField,
    ModalMode,
  },
  props: {
    title: {
      type: String,
    },
    mode: {
      type: String, // "table" | 'modal'
      default: "table",
    },
    columns: {
      type: Array,
      default: () => [],
    },
    data: {
      type: Array,
      default: () => [],
    },
    size: {
      type: String,
      default: "mini",
    },
    rules: {
      type: Object,
      default: () => ({}),
    },
    onConfirm: {
      type: Function,
    },
    readonly: {
      type: Boolean,
    },
  },
  watch: {
    proxyData: {
      handler(newVal) {
        this.$emit(
          "update:data",
          (newVal || []).map(({ editing: _, ...rest }) => ({ ...rest }))
        );
      },
      deep: true,
      immediate: true,
    },
  },
  data() {
    return {
      action: "add", // add | edit
      editIndex: -1,
      proxyData: [],
      _defaultData: {},
      hasEditing: false,
      modalVisible: false,
    };
  },
  mounted() {
    this.$nextTick(() => {
      this.update(this.data);
    });
  },
  methods: {
    handleValueChange(val, prop, index) {
      this.$set(this.proxyData, index, {
        ...this.proxyData[index],
        [prop]: val,
      });

      this.onRowUpdate(this.proxyData[index], index);
    },
    getDefaultData() {
      const columns = this.columns.filter(({ type }) => type !== "index");
      const data = columns.reduce(
        (prev, current) => ({
          ...prev,
          [current.prop]: "",
        }),
        {}
      );

      return {
        ...data,
        editing: true,
      };
    },
    update(data = []) {
      this.proxyData = data.map((item) => ({
        ...item,
        editing: false,
      }));
    },
    onInsertData() {
      this.action = "add";
      this.editIndex = this.proxyData.length;

      switch (this.mode) {
        case "table":
          if (this.isHasEditing()) return;
          this.$set(this.proxyData, this.proxyData.length, this.getDefaultData());
          this.hasEditing = true;
          break;
        case "modal":
          this._defaultData = this.getDefaultData();
          this.modalVisible = true;
          break;
        default:
          break;
      }
    },
    onCurrentRowDelete(index) {
      if (this.mode === "table" && this.isHasEditing()) {
        return;
      }

      this.proxyData.splice(index, 1);
    },
    onCurrentRowEdit(row, index) {
      this.action = "edit";
      this.editIndex = index;

      switch (this.mode) {
        case "table":
          if (this.isHasEditing()) return;
          this.$set(this.proxyData, index, { ...row, editing: true });
          this.hasEditing = true;
          break;
        case "modal":
          this._defaultData = { ...this.proxyData[index] };
          this.modalVisible = true;
          break;
        default:
          break;
      }
    },
    onRowUpdate(row, index) {
      this.$emit("rowUpdate", {
        row,
        index,
      });
    },
    isHasEditing() {
      if (this.hasEditing) {
        this.$message.warning("请先保存编辑中的数据");
      }
      return this.hasEditing;
    },
    validate() {
      return !this.isHasEditing();
    },
    onCurrentRowSave(row, index) {
      const updateFn = () => {
        this.$set(this.proxyData, index, { ...row, editing: false });
        this.editIndex = -1;
        this.hasEditing = false;
      };

      this.mode === "table"
        ? this.$refs.ruleForm.isHasEditing((isValid) => isValid && updateFn())
        : updateFn();
    },
  },
};
</script>
