<template>
  <div class="custom-select-tree">
    <el-select
      ref="elSelect"
      v-model="selectedList"
      :popper-class="popperClass"
      :clearable="clearable"
      :disabled="disabled"
      :placeholder="placeholder"
      :style="styles"
      :filterable="filterable"
      :multiple="multiple"
      :collapse-tags="collapseTags"
      @remove-tag="handleRemoveTag"
      @clear="clear"
      @change="handelSelectChange"
      @visible-change="handleVisibleChange"
    >
      <el-option v-if="treeList && treeList.length > 0" :value="inputVal">
          <el-tree
            ref="elTree"
            class="org-range-tree"
            node-key="code"
            style="maxHeight:245px;maxWidth:520px;"
            :data="treeList"
            :indent="indent"
            :highlight-current="true"
            :default-expand-all="true"
            :expand-on-click-node="false"
            check-strictly
            :props="defaultProps"
            :show-checkbox="showCheckbox"
            :render-content="renderContent"
            @check="handleChecked"
            @check-change="handleCheckedChange"
          >
            <div class="custom-tree-node" slot-scope="{node, data}">
              <span class="node-label" :title="node.label">{{ node.label }}</span>
              <el-button
                v-if="data.id !== '0'"
                type="text"
                class="node-btn"
                :class="{
                  'check-node': node.data.isCurrentAndLowerLevel
                }"
                size="mini"
                @click="() => handleSelected(node, data)"
              >
                本级及下级
              </el-button>
            </div>
          </el-tree>
      </el-option>
    </el-select>
  </div>
</template>
<script>
import utils from '@/hotent-ui-util.js'

export default {
  name: 'CustomSelectTree',
  props: {
    popperClass: {
      type: String,
      default: 'custom-tree__select'
    },
    styles: {
      type: Object,
      default() {
        return {}
      }
    },
    clearable: {
      type: Boolean,
      default: true
    },
    filterable: {
      type: Boolean,
      default: false
    },
    indent: {
      type: Number,
      default: 8
    },
    showCheckbox: {
      type: Boolean,
      default: false
    },
    multiple: {
      type: Boolean,
      default: false
    },
    renderContent: Function,
    treeData: Array,
    placeholder: {
      type: String,
      default: '请选择'
    },
    disabled: {
      type: Boolean,
      default: false
    },
    selectedOrg: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      treeList: [],
      defaultProps: {
        children: 'children',
        label: 'name'
      },
      valueDesc: '',
      selectedList: [],
      childrenData: [],
      treeDataCopy: [],
      currentSelectedOrg:[],
      collapseTags:true,
      initialInputHeight:0,
      deleteOrgCode:[]
    }
  },
  computed: {
    inputVal: {
      get: function() {
        if (!this.value) {
          return ''
        }
        return this.value
      },
      set: function(val) {
        this.$emit('input', val)
      }
    }
  },
  watch: {
    treeData:{
      handler(val){
        if (val&&val.length) {
        const cloneTreeList = _.cloneDeep(val)
        if (this.selectedOrg && this.selectedOrg.length) {
          const codeList = this.selectedOrg.map(item => item.code)
          const selectedObj = this.selectedOrg.reduce((pre, cur) => {
            pre[cur.code] = cur.isCurrentAndLowerLevel
            return pre
          }, {})
          const flatTreeList = utils.nest2tile(cloneTreeList)
          const list = flatTreeList.map(it => {
            return {
              ...it,
              isCurrentAndLowerLevel: selectedObj[it.code]
                ? selectedObj[it.code]
                : it.isCurrentAndLowerLevel,
              isChecked:codeList.includes(it.code) ? true : false,
             
            }
          }) 
          const filterList = _.cloneDeep(list)
           const checkedCodeList = filterList.filter(item=>item.isChecked).map(it=>it.code)
           this.deleteOrgCode = this.selectedOrg.filter(item=>!checkedCodeList.includes(item.code)).map(it=>it.code)
          this.selectedList = this.selectedOrg.map(item=>{
            if(this.deleteOrgCode.includes(item.code)){
              return item.code
            }else{
              return item.name
            }
          })
          //获取选择本级及下级的组织ID
          const orgIds = filterList
            .filter(item => item.isCurrentAndLowerLevel)
            .map(item => item.id)
          const newList = filterList.filter(
            item => !orgIds.includes(item.parentId)
          )
          const data = _.cloneDeep(utils.tile2nest(newList))
          if (data.length > 1) {
            this.treeList = [data[0]]
          } else {
            this.treeList = data
          }
          this.$nextTick(() => {
            if(this.$refs.elTree){
              this.$refs.elTree.setCheckedKeys(codeList)
            }
          })
        } else {
          this.treeList = cloneTreeList
        }
      }
      },
      immediate:true
    },
    selectedList: {
      handler(val) {
        if (val.length < 1) {
          this.$refs.elTree.setCheckedKeys([])
          this.treeList = _.cloneDeep(this.treeData)
        }
      },
      deep: true
    }
  },
  mounted() {
    this.treeDataCopy = this.treeData
    this.currentSelectedOrg = this.selectedOrg
    const input = this.$refs.elSelect.$el.querySelector('input')
    this.initialInputHeight = input.getBoundingClientRect().height
  },
  methods: {
    setDeleteRoleStyle(){
      const tags = this.$refs.elSelect.$refs.tags;
      const tagSpans = Array.from(tags.getElementsByClassName('el-tag'))
      tagSpans.forEach((item=>{
        if(this.deleteOrgCode.includes(item.innerText)){
          item.className =  'el-tag el-tag--danger el-tag--mini el-tag--light'
          item.title = '该组织已被删除'
        }else{
          item.className =  'el-tag el-tag--info el-tag--mini el-tag--light'
          item.title = ''
        }
      }))
    },
    handleCheckedChange(){
       this.$nextTick(()=>{
        this.setDeleteRoleStyle()
      })
    },
    clear() {
      this.changeIsCurrentAndLowerLevel(this.treeList)
      this.currentSelectedOrg = []
      this.deleteOrgCode = []
      this.selectedList = []
      this.$refs.elTree.setCheckedKeys([])
    },
    changeIsCurrentAndLowerLevel(data) {
      data.forEach(item => {
        item.isChecked = false
        if (item.isCurrentAndLowerLevel) {
          item.isCurrentAndLowerLevel = false
        }
        if (item.children && item.children.length) {
          this.changeIsCurrentAndLowerLevel(item.children)
        }
      })
    },
    //设置当前节点是否选择本级及下级
    setCurrentNodeIsNext(data,name){
      const treeList = _.cloneDeep(data)
      treeList.forEach(item=>{
        item.isChecked = false
        if(item.name === name){
          item.isCurrentAndLowerLevel = false
        }
        if(item.children && item.children.length){
          this.setCurrentNodeIsNext(item.children,name)
        }
      })
      this.treeList = [...treeList]
    },
    handleRemoveTag(tag) {
      this.setCurrentNodeIsNext(this.treeData,tag)
      this.currentSelectedOrg = this.currentSelectedOrg.filter(item=>item.code !== tag)
      this.currentSelectedOrg = this.currentSelectedOrg.filter(item=>item.name !== tag)
      this.$nextTick(()=>{
        this.setDeleteRoleStyle()
      })
      this.deleteOrgCode = this.deleteOrgCode.filter(item=>item !== tag)
      this.$emit('check', this.currentSelectedOrg)
    },
    handelSelectChange(val){
      const checkedNodeList = this.$refs.elTree.getCheckedNodes()
      const selectedKey = checkedNodeList
        .filter(item =>{
         return  val.includes(item.name)
        })
        .map(it => it.code)
      this.$refs.elTree.setCheckedKeys(selectedKey)
    },
    handleSelected(node, data) {
      this.$set(
        node.data,
        'isCurrentAndLowerLevel',
        !node.data.isCurrentAndLowerLevel
      )
      let checkedNodeList = this.$refs.elTree.getCheckedNodes()
      if (node.data.isCurrentAndLowerLevel) {
        const checkedKeys = checkedNodeList.map(item => item.code)
        this.$refs.elTree.setCheckedKeys(
          new Set([...checkedKeys, node.data.code])
        )
        if (node.childNodes && node.childNodes.length) {
          this.$set(data, 'children', [])
        }   
      } else {
        this.findCurrentChildren(this.treeData, data.code)
        if (this.childrenData && this.childrenData.length) {
          this.$set(data, 'children', this.childrenData)
        }
      }
      this.currentSelectedOrg = this.currentSelectedOrg.map(item=>{
          return {
            ...item,
            isCurrentAndLowerLevel:item.code === data.code ? data.isCurrentAndLowerLevel : item.isCurrentAndLowerLevel
          }
        })
      if(!data.isChecked){
       this.$set(data,'isChecked',true)
       this.currentSelectedOrg.push(data)
      }
      this.$nextTick(()=>{
        this.selectedList = this.currentSelectedOrg.filter(item => item.id !== '0').map(item=>item.name)
        this.$emit('check', this.currentSelectedOrg)
      })
    },
    findCurrentChildren(treeData, code) {
      const data = _.cloneDeep(treeData)
      if (!data) return
      for (let i = 0; i < data.length; i++) {
        if (data[i].code === code) {
          this.childrenData = data[i].children
          return
        } else {
          if (data[i].children) {
            this.findCurrentChildren(data[i].children, code)
          }
        }
      }
    },
    handleChecked(data){
      this.$set(data,'isChecked',data.isChecked ? false : true)
      if(data.isChecked){
        this.currentSelectedOrg.push(data)
      }else{
        this.currentSelectedOrg = this.currentSelectedOrg.filter(item=>item.code !== data.code)
        this.$set(data,'isCurrentAndLowerLevel',false)
      }
      const list = this.currentSelectedOrg.filter(item => item.id !== '0')
      this.selectedList = list.map(item => item.name)
      this.$emit('check', list)
    },
    handleVisibleChange(val){
      this.collapseTags = !val
      this.$nextTick(()=>{
        if(val){
          const tree = this.$refs.elTree&&this.$refs.elTree.$el.querySelector('.el-tree-node__content .el-icon-caret-right')
          tree.style.pointerEvents = "none"
        }
       const input = this.$refs.elSelect.$el.querySelector('input');
        const tags = this.$refs.elSelect.$refs.tags;
        tags.style.flexWrap = val ? 'wrap' : 'nowrap'
        const tagsHeight = tags ? Math.round(tags.getBoundingClientRect().height) : 0;
        const sizeInMap = this.initialInputHeight || 40;
        input.style.height = !val
          ? '32px'
          : Math.max(
            tags ? (tagsHeight + (tagsHeight > 32 ? 6 : 0)) : 0,
            sizeInMap
          ) + 'px';
          const tagSpans = Array.from(tags.getElementsByClassName('el-tag'))
          tagSpans.forEach((item=>{
            if(this.deleteOrgCode.includes(item.innerText)){
              item.className =  'el-tag el-tag--danger el-tag--mini el-tag--light'
              item.title = '该组织已被删除'
            }
          }))
        })
    }
  }
}
</script>
<style lang="scss" scoped>
div[aria-invalid='true'] {
  ::v-deep {
    .el-input__inner,
    .el-input__inner:focus {
      border-color: #f56c6c;
    }
  }
}

.custom-select-tree {
  ::v-deep {
    .el-select {
      width: 100%;
      .el-select__tags{
        max-width: 136px !important;
        flex-wrap: nowrap;
      }
    }
    .el-tag.el-tag--danger{
      .el-tag__close{
        background-color: rgba(229, 85, 85,0.26);
        &:hover{
          background-color: rgba(229, 85, 85,1);
        }
      }
    }
  }
}

.el-select-dropdown__item.hover,
.el-select-dropdown__item:hover {
  padding-right: 0;
  padding-left: 0;
  background-color: #fff;
}

.el-select-dropdown__item {
  font-size: 14px;
  padding: 0 20px;
  position: relative;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: #606266;
  height: 100%;
  line-height: 34px;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  cursor: pointer;
}

li.el-select-dropdown__item.selected {
  font-weight: normal;
  padding-right: 0;
  padding-left: 0;
}
</style>
