<template>
  <el-dialog
    class="select-user-dialog"
    :visible.sync="modalIsShow"
    title="选择考试对象"
    top="10vh"
    width="600px"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    append-to-body
    @opened="visibleChange"
  >
    <div class="user-search">
      <el-input
        v-model="filterLabel"
        placeholder="请输入班级名称"
        clearable
        size="mini"
        prefix-icon="el-icon-search"
        @input="labelChange"
      ></el-input>
    </div>

    <el-row type="flex" :gutter="10">
      <el-col :span="12">
        <h3 class="user-part-title">
          {{ showStudent ? "班级/学生" : "班级" }}
        </h3>
        <div class="user-tree">
          <el-tree
            ref="UserTree"
            :data="userTree"
            node-key="id"
            show-checkbox
            check-on-click-node
            :expand-on-click-node="false"
            :props="defaultProps"
            @check="checkChange"
          >
          </el-tree>
        </div>
      </el-col>
      <el-col :span="12">
        <h3 class="user-part-title">已选范围</h3>
        <div class="user-tree">
          <el-tree
            ref="UserSelectedTree"
            :data="selectedUsers"
            node-key="id"
            default-expand-all
            :props="defaultProps"
          >
            <span class="custom-tree-node" slot-scope="{ node, data }">
              <span>{{ data.label }}</span>
              <el-button
                type="text"
                icon="el-icon-remove"
                class="color-danger"
                @click.stop="removeSelectStudent(node)"
              >
              </el-button>
            </span>
          </el-tree>
        </div>
      </el-col>
    </el-row>

    <div slot="footer">
      <el-button type="primary" :disabled="loading" @click="submit"
        >确认</el-button
      >
      <el-button @click="cancel">取消</el-button>
    </div>
  </el-dialog>
</template>

<script>
import { uploadOrFindExamTaskStudent } from "../../api";

export default {
  name: "modify-exam-task-student",
  props: {
    disabledIds: {
      type: Array,
      default() {
        return [];
      },
    },
    selectedIds: {
      type: Array,
      default() {
        return [];
      },
    },
    filterParams: {
      type: Object,
      default() {
        return {
          courseCode: "",
          examId: "",
        };
      },
    },
    showStudent: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      modalIsShow: false,
      filterCache: {},
      dataTree: [],
      userTree: [],
      selectedUsers: [],
      filterLabel: "",
      loading: false,
      defaultProps: {
        children: "children",
        label: "label",
        disabled: "disabled",
      },
    };
  },
  methods: {
    async getStudents() {
      let datas = {
        ...this.filterParams,
      };
      const data = await uploadOrFindExamTaskStudent(datas);
      this.dataTree = this.parseStudentData(data);
    },
    parseStudentData(data) {
      const disabledStdIds = this.disabledIds.map((item) => item.split("_")[1]);
      return data.map((item) => {
        let nitem = {
          id: item.clazzId,
          label: item.clazzName,
          clazzId: item.clazzId,
          clazzName: item.clazzName,
          studentClazzType: item.studentClazzType,
          children: [],
        };

        nitem.children = item.studentInfoList.map((elem) => {
          return {
            ...elem,
            disabled: disabledStdIds.includes(elem.studentId),
            isUser: true,
            id: `${item.clazzId}_${elem.studentId}`,
            label: elem.studentName,
            studentClazzType: item.studentClazzType,
          };
        });
        nitem.disabled = !nitem.children.some((elem) => !elem.disabled);

        return nitem;
      });
    },
    getUserTree() {
      let userTree = this.dataTree;
      if (this.showStudent) return userTree;

      return userTree.map((item) => {
        let nitem = { ...item };
        nitem.children = [];
        return nitem;
      });
    },
    checkChange() {
      // console.log("check click");
      const selectedKeys = this.$refs.UserTree.getCheckedKeys(true);
      if (!this.showStudent) {
        this.selectedUsers = this.userTree.filter((item) =>
          selectedKeys.includes(item.id)
        );
        return;
      }
      const disabledIds = [...selectedKeys, ...this.disabledIds];
      const disabledStdIds = disabledIds.map((item) => item.split("_")[1]);

      let selectedUsers = [];
      this.userTree.forEach((item) => {
        const children = item.children.filter((elem) =>
          selectedKeys.includes(elem.id)
        );
        if (children.length) {
          selectedUsers.push({
            ...item,
            children,
          });
        }
        // 同一个学生只允许选择一次
        item.children.forEach((elem) => {
          elem.disabled =
            !selectedKeys.includes(elem.id) &&
            disabledStdIds.includes(elem.studentId);
        });
        item.disabled = !item.children.some((elem) => !elem.disabled);
      });
      this.selectedUsers = selectedUsers;
    },
    removeSelectStudent(node) {
      // console.log("node remove");
      if (!this.showStudent) {
        this.selectedUsers = this.selectedUsers.filter(
          (item) => item.id !== node.data.id
        );
        this.$refs.UserTree.setCheckedKeys(
          this.selectedUsers.map((item) => item.id)
        );
        return;
      }

      this.$refs.UserSelectedTree.remove(node);
      this.setTreeSelectedKeys();
      this.checkChange();
    },
    setTreeSelectedKeys() {
      if (!this.showStudent) {
        const selectedUsersIds = this.selectedUsers.map((item) => item.id);
        this.$refs.UserTree.setCheckedKeys(selectedUsersIds);
        return;
      }
      let selectedUserIds = [];
      this.selectedUsers.forEach((item) => {
        item.children.forEach((elem) => {
          selectedUserIds.push(elem.id);
        });
      });
      this.$refs.UserTree.setCheckedKeys(selectedUserIds);
    },
    async visibleChange() {
      if (
        this.filterCache.courseCode !== this.filterParams.courseCode ||
        this.filterCache.examId !== this.filterParams.examId
      ) {
        await this.getStudents();
      }
      this.filterCache = { ...this.filterParams };

      this.$refs.UserTree.setCheckedKeys([]);
      this.selectedUsers = [];
      this.userTree = this.getUserTree();
      this.updateUserTreeDisableInfo(this.disabledIds);

      if (this.selectedIds && this.selectedIds.length) {
        this.$nextTick(() => {
          this.$refs.UserTree.setCheckedKeys(this.selectedIds);
          this.checkChange();
        });
      }
    },
    labelChange() {
      if (this.filterLabel) {
        const escapeRegexpString = (value = "") =>
          String(value).replace(/[|\\{}()[\]^$+*?.]/g, "\\$&");
        const reg = new RegExp(escapeRegexpString(this.filterLabel), "i");
        this.userTree = this.getUserTree().filter((item) =>
          reg.test(item.label)
        );
      } else {
        this.userTree = this.getUserTree();
      }
      this.setTreeSelectedKeys();
    },
    updateUserTreeDisableInfo(disabledIds) {
      if (!this.showStudent) return;
      const disabledStdIds = disabledIds.map((item) => item.split("_")[1]);

      this.userTree.forEach((item) => {
        item.children.forEach((elem) => {
          elem.disabled = disabledStdIds.includes(elem.studentId);
        });
        item.disabled = !item.children.some((elem) => !elem.disabled);
      });
    },
    cancel() {
      this.modalIsShow = false;
    },
    open() {
      this.modalIsShow = true;
    },
    getFullSelectedUsers() {
      let userTree = this.dataTree;
      const selectedUsersIds = this.selectedUsers.map((item) => item.id);
      return userTree.filter((item) => selectedUsersIds.includes(item.id));
    },
    submit() {
      if (!this.selectedUsers.length) {
        this.$message.error("请选择考试对象");
        return;
      }

      if (this.loading) return;
      this.loading = true;
      const selectedUsers = this.showStudent
        ? this.selectedUsers
        : this.getFullSelectedUsers();

      this.$emit("modified", {
        selectedStudents: selectedUsers,
        isSelectStudent: this.showStudent,
      });
      setTimeout(() => {
        this.loading = false;
      }, 500);
      this.cancel();
    },
  },
};
</script>
