<template>
  <div class="auth"
       v-show="show">
    <div :class="[showContainer ?'show': '','auth__cover']"
         @touchmove.prevent
         @click="closeTree"></div>
    <div :class="[showContainer ?'show': '','auth__container']">
      <div class="auth__header">
        <div class="auth__title">选择对应的权限</div>
        <div class="auth__selector">
          <input type="checkbox"
                 id="checkAllCheckbox"
                 class="auth__checkbox"
                 v-model="hasCheckedAll"
                 @change="checkAll">
          <label for="checkAllCheckbox"
                 class="auth__checkbox-txt mui-flex aic"><em class="auth__checkbox-icon"></em>全选</label>
        </div>
      </div>
      <div class="auth__list">
        <div class="auth__item"
             v-for="(item,index) in list"
             :key="item.id">
          <div class="auth__selector">
            <input type="checkbox"
                   ref="checkboxInput"
                   :id="item.id"
                   class="auth__checkbox"
                   v-model="item.checked"
                   @change="subChange(item,item.checked,$event)">
            <label :for="item.id"
                   class="auth__checkbox-txt mui-flex aic">
              <em class="auth__checkbox-icon"></em>
              <span>{{item.name}}</span>
              <label class="mui-flex__cell auth__toggle-box"
                     v-show="item.children.length"
                     @click.stop.prevent="toggleSubList(index)">
                <em class="auth__toggle-icon"
                    ref="toggle"></em>
              </label>
            </label>
          </div>
          <div class="auth__sub-list"
               ref="sublist">
            <div class="auth__selector"
                 v-for="subItem in item.children"
                 :key="subItem.id">
              <input type="checkbox"
                     :id="subItem.id"
                     class="auth__checkbox"
                     v-model="subItem.checked"
                     @change="parentChange(item,index)">
              <label :for="subItem.id"
                     class="auth__checkbox-txt mui-flex aic"><em class="auth__checkbox-icon"></em>{{subItem.name}}</label>
            </div>
          </div>
        </div>
      </div>
      <div class="auth__btn mui-flex aic">
        <div class="auth__btn-item mui-flex__cell"
             @click="closeTree">取消</div>
        <div class="auth__btn-item mui-flex__cell"
             @click="confirmSelect">确定</div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'AuthTree',
  props: {
    authlist: {
      type: Array,
      default: function() {
        return [];
      }
    },
    show: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      hasCheckedAll: false,
      defaultList: [],
      list: [],
      checkedList: [],
      showContainer: false
    };
  },
  watch: {
    authlist: {
      handler(val, oldVal) {
        this.defaultList = this.deepCopy(val);
        this.list = this.deepCopy(val);
        this.setHasCheckedAll();
        this.setHalfChecked(this.list);
      },
      immediate: true
    },
    show: {
      handler(val, oldVal) {
        const that = this;
        setTimeout(() => {
          that.showContainer = val;
        }, 60);
      },
      immediate: true
    }
  },
  methods: {
    toggleSubList(index) {
      let rotateStyle;
      let subHeight;
      const height = parseInt(this.$refs.sublist[index].style.height);
      if (height) {
        this.$refs.toggle[index].classList.remove('rotate');
        subHeight = 0;
      } else {
        this.$refs.toggle[index].classList.add('rotate');
        subHeight = this.$refs.sublist[index].scrollHeight + 'px';
      }
      this.$refs.toggle[index].style.transform = rotateStyle;
      this.$refs.sublist[index].style.height = subHeight;
    },
    deepCopy(obj) {
      const listString = JSON.stringify(obj);
      return JSON.parse(listString);
    },
    checkAll() {
      this.setHasCheckedAll();
      this.mapArray(this.list);
      this.hasCheckedAll = !this.hasCheckedAll;
      this.$refs.checkboxInput.map((item) => {
        item.classList.remove('half');
      });
    },
    subChange(node, checked, e) {
      if (e.target.classList.contains('half')) {
        e.target.classList.remove('half');
      }
      if (node.children.length) {
        node.children.map(item => {
          item.checked = checked;
        });
      }
      this.setHasCheckedAll();
    },
    parentChange(node, index) {
      const childrenLength = node.children.length;
      const subChecked = node.children.filter(item => {
        return item.checked === false;
      });
      if (subChecked.length === childrenLength) {
        this.$refs.checkboxInput[index].classList.add('half');
      } else {
        node.checked = true;
        if (subChecked.length !== 0) {
          this.$refs.checkboxInput[index].classList.add('half');
        } else {
          this.$refs.checkboxInput[index].classList.remove('half');
        }
      }
      this.setHasCheckedAll();
    },
    setHasCheckedAll() {
      this.hasCheckedAll = !this.findArray(this.list);
    },
    setHalfChecked(list) {
      list.map((item, index) => {
        if (item.checked && item.children.length) {
          const unCheckedBox = item.children.filter(node => {
            return node.checked === false;
          });
          if (unCheckedBox.length !== 0) {
            console.log(this, index);
            this.$nextTick(() => {
              this.$refs.checkboxInput[index].classList.add('half');
            });
          }
        }
      });
    },
    findArray(array) {
      return array.find(item => {
        if (item.checked && item.children.length) {
          this.findArray(item.children);
        }
        return item.checked === false;
      });
    },
    mapArray(array) {
      array.map(item => {
        item.checked = !this.hasCheckedAll;
        if (item.children.length) {
          this.mapArray(item.children);
        }
      });
    },
    getCheckedList(array) {
      array.map(item => {
        if (item.checked) {
          this.checkedList.push({
            'name': item.name,
            'relativeId': item.id,
            'type': item.type
          });
        }
        if (item.children.length) {
          this.getCheckedList(item.children);
        }
      });
    },
    confirmSelect() {
      this.checkedList = [];
      this.getCheckedList(this.list);
      this.$emit('getSelectedRole', this.list, this.checkedList);
      this.$emit('update:show', false);
    },
    closeTree() {
      this.$emit('update:show', false);
      this.$emit('closeAuthTree');
      this.list = this.deepCopy(this.defaultList);
      this.setHasCheckedAll();
    }
  }
};
</script>
