<template>
  <el-dialog
    class="modify-exam-student 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="mb-4 tab-btns">
      <el-button
        v-for="item in objectTypeList"
        :key="item.value"
        size="medium"
        :type="examObjectType === item.value ? 'primary' : 'default'"
        :disabled="
          selectedExamObjectType && selectedExamObjectType !== item.value
        "
        @click="selectMenu(item.value)"
        >{{ item.name }}
      </el-button>
    </div>
    <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";

const EXAM_OBJECT_TYPE = {
  TEACH_CLAZZ_STUDENT: "我教课程选择",
  BASIC_CLAZZ_STUDENT: "学生库选择",
};

export default {
  name: "modify-exam-student",
  props: {
    disabledIds: {
      type: Array,
      default() {
        return [];
      },
    },
    selectedIds: {
      type: Array,
      default() {
        return [];
      },
    },
    courseCode: {
      type: String,
      default: "",
    },
    objectTypes: {
      type: Array,
      default() {
        return ["TEACH_CLAZZ_STUDENT", "BASIC_CLAZZ_STUDENT"];
      },
    },
    showStudent: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      modalIsShow: false,
      examObjectType: "TEACH_CLAZZ_STUDENT",
      basicCourseCode: null,
      objectTypeList: [],
      dataTree: {
        TEACH_CLAZZ_STUDENT: [],
        BASIC_CLAZZ_STUDENT: [],
      },
      selectedExamObjectType: null,
      userTree: [],
      selectedUsers: [],
      filterLabel: "",
      loading: false,
      defaultProps: {
        children: "children",
        label: "label",
        disabled: "disabled",
      },
    };
  },
  methods: {
    async getStudents(examObjectType) {
      let datas = {
        examObjectType: examObjectType || this.examObjectType,
      };
      if (datas.examObjectType === "TEACH_CLAZZ_STUDENT")
        datas.courseCode = this.courseCode;
      const data = await uploadOrFindExamTaskStudent(datas);
      this.dataTree[datas.examObjectType] = 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;
      });
    },
    async selectMenu(val) {
      this.examObjectType = val;
      this.$refs.UserTree.setCheckedKeys([]);

      this.selectedUsers = [];

      if (!this.dataTree[val].length) {
        await this.getStudents();
      }
      this.userTree = this.getUserTree(val);
      this.updateUserTreeDisableInfo(this.disabledIds);
    },
    getUserTree(examObjectType) {
      let userTree = this.dataTree[examObjectType];
      if (this.showStudent) return userTree;

      return userTree.map((item) => {
        let nitem = { ...item };
        nitem.children = [];
        return nitem;
      });
    },
    clearTypeData(type = "BASIC_CLAZZ_STUDENT") {
      this.dataTree[type] = [];
    },
    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() {
      this.objectTypeList = this.objectTypes.map((field) => {
        return {
          name: EXAM_OBJECT_TYPE[field],
          value: field,
        };
      });
      if (!this.objectTypeList.length) return;
      if (this.objectTypeList.length === 1) {
        this.examObjectType = this.objectTypeList[0].value;
      }

      if (this.basicCourseCode !== this.courseCode) {
        this.clearSelectedExamObjectType();
        this.basicCourseCode = this.courseCode;
        await this.getStudents(this.examObjectType);
      }

      await this.selectMenu(this.examObjectType);

      if (this.selectedIds && this.selectedIds.length) {
        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(this.examObjectType).filter((item) =>
          reg.test(item.label)
        );
      } else {
        this.userTree = this.getUserTree(this.examObjectType);
      }
      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);
      });
    },
    clearSelectedExamObjectType() {
      this.selectedExamObjectType = null;
    },
    cancel() {
      this.modalIsShow = false;
    },
    open() {
      this.modalIsShow = true;
    },
    getFullSelectedUsers() {
      let userTree = this.dataTree[this.examObjectType];
      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;
      this.selectedExamObjectType = this.examObjectType;
      const selectedUsers = this.showStudent
        ? this.selectedUsers
        : this.getFullSelectedUsers();

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