<template>
  <div class="menu_permission">
    <ul
      class="floor_list first"
      v-if="permissionsList && permissionsList.length"
    >
      <li
        v-for="(first_item, first_index) in permissionsList"
        :key="'p_' + first_index"
      >
        <menu-checkbox
          class="floor_item first"
          :item="first_item"
          @click.native="selectedItem(first_item)"
        ></menu-checkbox>
        <ul
          class="floor_list second"
          v-if="first_item.Child && first_item.Child.length"
        >
          <li
            v-for="(second_item, second_index) in first_item.Child"
            :key="'p_' + first_index + '_' + second_index"
          >
            <menu-checkbox
              class="floor_item second"
              :item="second_item"
              @click.native="selectedItem(second_item, first_item)"
            ></menu-checkbox>
            <ul
              class="floor_list third"
              v-if="second_item.Child && second_item.Child.length"
            >
              <li
                v-for="(third_item, third_index) in second_item.Child"
                :key="
                  'p_' + first_index + '_' + second_index + '_' + third_index
                "
              >
                <menu-checkbox
                  class="floor_item third"
                  :item="third_item"
                  @click.native="
                    selectedItem(third_item, second_item, first_item)
                  "
                ></menu-checkbox>
                <ul
                  class="floor_list fourth"
                  v-if="third_item.Child && third_item.Child.length"
                >
                  <li>
                    <menu-checkbox
                      v-for="(fourth_item, fourth_index) in third_item.Child"
                      :key="
                        'p_' +
                          first_index +
                          '_' +
                          second_index +
                          '_' +
                          third_index +
                          '_' +
                          fourth_index
                      "
                      class="floor_item fourth"
                      :item="fourth_item"
                      @click.native="
                        selectedItem(
                          fourth_item,
                          third_item,
                          second_item,
                          first_item
                        )
                      "
                    ></menu-checkbox>
                  </li>
                </ul>
              </li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
  </div>
</template>

<script>
import menuCheckbox from "./menu-checkbox";

export default {
  components: {
    menuCheckbox,
  },
  model: {
    prop: "permissions",
    event: "change-permissions",
  },
  props: {
    permissions: {
      type: Array,
      default: () => [],
    },
    list: {
      type: Array,
      default: () => [],
    },
  },
  data: () => ({
    initFlag: true,
    permissionsList: [],
  }),
  watch: {
    permissions: {
      handler() {
        this.init();
      },
      deep: true,
    },
  },
  methods: {
    init() {
      if (!this.initFlag) {
        return;
      }

      // console.log("menu permission init.");
      let permissionsList = this.deepClone(this.list);
      let permissions = this.permissions;

      permissionsList.forEach((item) => {
        this.traverse(item, (item) => {
          let target = permissions.find((v) => v.menu_id === item.menu_id);

          this.$set(item, "selected", target ? 1 : 0);
        });
      });

      this.permissionsList = permissionsList;
      this.initPermissionsList();
    },
    traverse(obj, cb) {
      cb(obj);

      if (obj.Child && obj.Child.length) {
        obj.Child.forEach((item) => {
          this.traverse(item, cb);
        });
      }
    },
    deepClone(source) {
      if (!source || typeof source !== "object") {
        throw new Error("error arguments from deepClone");
      }

      let result = source.constructor === Array ? [] : {};

      for (let key in source) {
        if (source[key] && typeof source[key] === "object") {
          result[key] = source[key].constructor === Array ? [] : {};
          result[key] = this.deepClone(source[key]);
        } else {
          result[key] = source[key];
        }
      }

      return result;
    },
    selectedItem(
      selected_item,
      p_item = null, // 父元素
      gp_item = null, // 祖父元素
      ggp_item = null // 曾祖父元素
    ) {
      let selected = selected_item.selected === 1 ? 0 : 1;

      this.traverse(selected_item, (item) => {
        this.$set(item, "selected", selected);
      });

      if (p_item) {
        this.upParentSelected(p_item);
      }

      if (gp_item) {
        this.upParentSelected(gp_item);
      }

      if (ggp_item) {
        this.upParentSelected(ggp_item);
      }

      this.uppermissions();
    },
    initPermissionsList() {
      const getSelectedState = (item) => {
        let selected = item.selected;
        let child = item.Child || [];

        if (child.length > 0 && selected !== 0) {
          let selectedLength1 = 0;
          let selectedLength2 = 0;

          child.forEach((v) => {
            let v_selected = getSelectedState(v);

            if (v_selected === 1) {
              selectedLength1++;
            } else if (v_selected === 2) {
              selectedLength2++;
            }
          });

          if (selectedLength1 === child.length) {
            selected = 1;
          } else if (selectedLength1 + selectedLength2 > 0) {
            selected = 2;
          }

          item.selected = selected;
        }

        return selected;
      };

      this.permissionsList.forEach((item) => {
        getSelectedState(item);
      });

      // this.$emit("change-list", this.permissionsList);
    },
    upParentSelected(parent) {
      let selectedLength1 = 0;
      let selectedLength2 = 0;
      let selected = parent.selected;

      parent.Child.forEach((item) => {
        if (item.selected === 1) {
          selectedLength1++;
        } else if (item.selected === 2) {
          selectedLength2++;
        }
      });

      if (selectedLength1 === parent.Child.length) {
        selected = 1;
      } else if (selectedLength1 + selectedLength2 > 0) {
        selected = 2;
      } else {
        selected = 0;
      }

      this.$set(parent, "selected", selected);
    },
    uppermissions() {
      let permissions = [];

      this.permissionsList.forEach((item) => {
        this.traverse(item, (item) => {
          if (item.selected !== 0) {
            permissions.push({
              menu_name: item.menu_name,
              menu_id: item.menu_id,
            });
          }
        });
      });

      this.initFlag = false;

      // this.$emit("change-list", this.permissionsList);
      this.$emit("change-permissions", permissions);
    },
  },
  mounted() {
    this.init();
  },
};
</script>

<style scoped>
.floor_list > li {
  display: flex;
  justify-content: flex-start;
  align-items: stretch;
}
.floor_list.first > li {
  border: 2px solid #f4f7fc;
  border-radius: 7px;
  overflow: hidden;
}
.floor_list:not(.first) {
  flex-grow: 1;
}
.floor_list:not(.first) > li {
  border-left: 2px solid #f4f7fc;
  border-top: 2px solid #f4f7fc;
  margin: -2px 0 0 -2px;
}
.floor_list.first > li:not(:first-child) {
  margin-top: 20px;
}
.floor_item {
  min-width: 230px;
  padding: 10px 30px;
  display: flex;
  justify-content: center;
  align-items: center;
}
.floor_item.fourth {
  width: 100%;
  justify-content: flex-start;
}
</style>
