<template>
  <div class="privilege-set">
    <table class="table">
      <colgroup>
        <col width="120" />
        <col width="120" />
        <col width="140" />
        <col width="60" />
        <col width="210" />
      </colgroup>
      <tbody>
        <tr>
          <th v-for="(item, index) in tableHead" :key="index">{{ item }}</th>
        </tr>
        <tr v-for="row in tableData" :key="row.id">
          <td v-for="(col, cindex) in row.columns" :key="cindex">
            <div v-if="col && col.type === 'page'">{{ col.name }}</div>
            <div v-else-if="col && col.type === 'page-checkbox'">
              <el-checkbox
                v-model="row.enable"
                :disabled="row.disabled"
                @change="(enable) => pageSelectChange(row, enable)"
              ></el-checkbox>
            </div>
            <div
              v-else-if="
                row.isPage && col && col.type === 'page-data-permission'
              "
            >
              <el-select
                v-model="row.dataPermissionType"
                class="width-200"
                placeholder="请选择"
                :disabled="row.disabled"
              >
                <el-option
                  v-for="(val, key) in DATA_PRIVILEGE_TYPE"
                  :key="key"
                  :value="key"
                  :label="val"
                ></el-option>
              </el-select>
            </div>
            <div v-else-if="col && col.type">
              <div
                class="cell-check-list"
                v-for="item in col.datas"
                :key="item.field"
              >
                <el-checkbox
                  v-model="item.enable"
                  :disabled="item.disabled"
                  @change="(enable) => typeSelectChange(row, enable)"
                  >{{ item.name }}</el-checkbox
                >
              </div>
            </div>
            <div v-else></div>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
import { DATA_PRIVILEGE_TYPE } from "../../../constants/enumerate";

export default {
  name: "privilege-set",
  props: {
    menus: {
      type: Array,
      default() {
        return [];
      },
    },
    showPermission: {
      type: Boolean,
      default: true,
    },
    disabledPermissionUrls: {
      type: Array,
      default() {
        return ["TaskApplyManage", "TaskReviewManage"];
      },
    },
  },
  data() {
    return {
      maxDeep: 0,
      tableData: [],
      tableHead: [],
      DATA_PRIVILEGE_TYPE,
    };
  },
  created() {
    this.initData();
  },
  methods: {
    initData() {
      this.maxDeep = this.getNavsDeep();
      this.tableHead = this.buildTableHead();
      // this.buildTableData();
    },
    getNavsDeep() {
      let maxDeep = 0;
      const getDeep = (navs, deep) => {
        ++deep;
        navs.forEach((nav) => {
          if (maxDeep < deep) maxDeep = deep;

          if (nav.children && nav.children.length) getDeep(nav.children, deep);
        });
      };
      getDeep(this.menus, maxDeep);

      return maxDeep;
    },
    buildTableHead() {
      let headers = [];
      let codes = ["一", "二", "三", "四", "五", "六", "七", "八"];
      for (let index = 0; index < this.maxDeep; index++) {
        headers.push(`${codes[index]}级页面`);
      }
      headers = [...headers, "页面"];
      if (this.showPermission) headers.push("数据权限");
      headers = [...headers, "查询条件", "功能按钮", "列表展示", "操作列"];

      return headers;
    },
    buildTableData(
      privilegeIds = [],
      dataPermissionInfo = [],
      disabledIds = []
    ) {
      let tableData = [];
      const privColumnCount = this.showPermission ? 6 : 5;
      let tableColumnCount = this.maxDeep + privColumnCount;
      const pageSetTypes = ["conditions", "buttons", "lists", "links"];

      let datePermissionMap = {};
      dataPermissionInfo.forEach((item) => {
        datePermissionMap[item.privilegeId] = item.dataPermissionType;
      });
      const buildData = (navs, deep) => {
        ++deep;
        navs.forEach((nav) => {
          const isDisabledPermissionUrl = this.disabledPermissionUrls.includes(
            nav.url
          );
          let columns = new Array(tableColumnCount);
          columns[deep - 1] = { type: "page", name: nav.name };
          columns[this.maxDeep] = {
            type: "page-checkbox",
          };
          if (this.showPermission && !isDisabledPermissionUrl) {
            columns[this.maxDeep + 1] = {
              type: "page-data-permission",
            };
          }

          const isPage = pageSetTypes.some(
            (type) => nav[type] && nav[type].length
          );
          const offsetPageSetInd = this.showPermission ? 2 : 1;
          if (isPage) {
            pageSetTypes.forEach((type, index) => {
              const datas = !nav[type]
                ? []
                : nav[type].map((elem) => {
                    let data = { ...elem };
                    data.enable = privilegeIds.includes(elem.id);
                    data.disabled = disabledIds.includes(elem.id);
                    return data;
                  });
              columns[this.maxDeep + index + offsetPageSetInd] = {
                type,
                datas,
              };
            });
          }

          tableData.push({
            id: nav.id,
            name: nav.name,
            url: nav.url,
            enable: privilegeIds.includes(nav.id),
            disabled: disabledIds.includes(nav.id),
            dataPermissionType:
              isPage && this.showPermission && !isDisabledPermissionUrl
                ? datePermissionMap[nav.id] || "SELF"
                : null,
            type: nav.type,
            parentId: nav.parentId,
            isPage,
            columns,
          });

          if (nav.children && nav.children.length)
            buildData(nav.children, deep);
        });
      };
      buildData(this.menus, 0);

      this.tableData = tableData;
    },
    resetdataPermissionType(val) {
      this.tableData.forEach((item) => {
        if (
          item.isPage &&
          !item.disabled &&
          this.showPermission &&
          !this.disabledPermissionUrls.includes(item.url)
        )
          item.dataPermissionType = val;
      });
    },
    getSelectedPrivileges() {
      let privilegeIds = [];
      let dataPermissionInfo = [];
      this.tableData
        .filter((row) => row.enable)
        .forEach((row) => {
          privilegeIds.push(row.id);
          dataPermissionInfo.push({
            privilegeId: row.id,
            dataPermissionType: row.dataPermissionType,
          });
          row.columns.forEach((column) => {
            if (!column.datas || !column.datas.length) return;

            column.datas.forEach((item) => {
              if (item.enable) privilegeIds.push(item.id);
            });
          });
        });
      return { privilegeIds, dataPermissionInfo };
    },
    // set change
    pageSelectChange(row, enable) {
      this.changRowColumnEnable(row, enable);
      this.changeParentNodeSelected(row.parentId, enable);
      this.changeChildrenNodeSelected(row.id, enable);
    },
    typeSelectChange(row, enable) {
      if (!row.enable && enable) {
        row.enable = enable;
        this.changeParentNodeSelected(row.parentId, enable);
        this.changeChildrenNodeSelected(row.id, enable);
      }
    },
    changRowColumnEnable(row, enable) {
      if (!row.isPage) return;
      row.columns.forEach((column) => {
        if (!column.datas || !column.datas.length) return;

        column.datas.forEach((item) => {
          item.enable = enable;
        });
      });
    },
    changeParentNodeSelected(parentId, enable) {
      if (!parentId) return;
      let curParentId = parentId;
      if (enable) {
        while (curParentId) {
          let curParentNode = this.tableData.find(
            (row) => row.id === curParentId
          );
          curParentNode.enable = enable;
          curParentId = curParentNode.parentId;
          this.changRowColumnEnable(curParentNode, enable);
        }
      } else {
        while (curParentId) {
          let curParentNode = this.tableData.find(
            (row) => row.id === curParentId
          );
          let childrenHasOneSelected = this.tableData
            .filter((row) => row.parentId === curParentId)
            .some((row) => row.enable);
          curParentNode.enable = childrenHasOneSelected;
          curParentId = curParentNode.parentId;
          this.changRowColumnEnable(curParentNode, enable);
        }
      }
    },
    changeChildrenNodeSelected(id, enable) {
      if (!id) return;
      let curIds = [id];
      while (curIds.length) {
        const validNodes = this.tableData.filter((row) =>
          curIds.includes(row.parentId)
        );
        validNodes.forEach((row) => {
          row.enable = enable;
          this.changRowColumnEnable(row, enable);
        });
        curIds = validNodes.map((row) => row.id);
      }
    },
  },
};
</script>
