<template>
  <a-card :class="$style.treewrap">
    <a-spin v-if="spinning" :spinning="spinning" :class="$style.spin" />
    <template v-else>
      <a-tree
        v-if="treeData.length > 0"
        :key="updateKey"
        :block-node="true"
        :tree-data="treeData"
        :selected-keys="selectedKeys"
        :default-expanded-keys="defaultExpandedKeys"
        :load-data="onLoadTreeData"
        @select="onTreeSelect"
        @expand="onExpand"
      >
      </a-tree>
      <a-empty v-else />
    </template>
  </a-card>
</template>

<script>
import NavService from './nav-service'
import components from './_import-components/sd-nav-tree-import'

export default {
  name: 'SdNavTree',
  metaInfo: {
    title: 'SdNavTree',
  },
  components,
  props: {
    hieraInfo: {
      type: Object,
      default: () => {},
    },
    rootData: {
      type: Object,
      default: () => {},
    },
  },
  data() {
    return {
      spinning: true,
      treeData: [],
      root: null,
      defaultExpandedKeys: [],
      selectedKeys: [],
      updateKey: 0,
    }
  },

  created() {
    this.onLoadTreeData()
  },
  methods: {
    onExpand(expandedKeys, { expanded, node }) {
      if (!expanded) {
        const newKeys = expandedKeys.concat([])
        this.filterChild(node, newKeys)
        expandedKeys = newKeys
      }
      this.defaultExpandedKeys = expandedKeys
    },
    filterChild(node, keys) {
      if (node.dataRef?.children) {
        node.dataRef.children.forEach((item) => {
          const index = keys.indexOf(item.key)
          if (index > -1) {
            keys.splice(index, 1)
          }
          this.filterChild(item, keys)
        })
      }
      if (node.children) {
        node.children.forEach((item) => {
          const index = keys.indexOf(item.key)
          if (index > -1) {
            keys.splice(index, 1)
          }
          this.filterChild(item, keys)
        })
      }
    },
    onTreeSelect(key, e) {
      this.selectedKeys = [e.node.dataRef.key]
      this.$emit('treeSelect', {
        id: e.node.dataRef.key,
        text: e.node.dataRef.title,
        groupId: this.getGroupId(e.node.dataRef).pop(),
      })
    },
    onLoadTreeData(treeNode) {
      return new Promise((resolve) => {
        let defaultExpandedKeys = this.defaultExpandedKeys.concat([])
        if (treeNode) {
          if (treeNode.dataRef.children) {
            resolve()
            return
          }
          NavService.getTreeChild({
            productMode: true,
            parentId: treeNode.dataRef.key,
          }).then((deps) => {
            treeNode.dataRef.children = this.parseTreeData(
              deps.data,
              treeNode.dataRef.fullpath,
              defaultExpandedKeys
            )
            this.treeData = [...this.treeData]
            this.spinning = false
            resolve()
          })
        } else {
          const oNodes = [
            {
              key: '-1',
              title: '可管理机构菜单',
              isLeaf: false,
              backendAttr: {},
              showAction: false,
              fullpath: [0],
              scopedSlots: {
                title: 'root',
              },
            },
          ]
          if (defaultExpandedKeys.length === 0) {
            this.loadExpand(oNodes, 1).then((ids) => {
              this.treeData = oNodes
              this.defaultExpandedKeys = ids
              const defaultNode = this.treeData[0].children[0]
              if (defaultNode) {
                this.selectedKeys = [defaultNode.key]
                this.$emit('treeSelect', {
                  id: defaultNode.key,
                  text: defaultNode.title,
                  groupId: this.getGroupId(defaultNode).pop(),
                })
              }
              this.spinning = false
              resolve()
            })
          } else {
            defaultExpandedKeys = defaultExpandedKeys.filter((item) => {
              return item !== '-1'
            })
            this.loadBeforeExpand(oNodes, defaultExpandedKeys).then(() => {
              this.treeData = oNodes
              this.spinning = false
              resolve()
            })
          }
        }
      })
    },

    loadBeforeExpand(oNodes, defaultExpandedKeys) {
      // 默认加载并展开之前展开的树
      return new Promise((resolve) => {
        Promise.all(
          oNodes
            .filter((oNode) => {
              return this.defaultExpandedKeys.indexOf(oNode.key) > -1
            })
            .map((oNode) => {
              return NavService.getTreeChild({
                productMode: true,
                parentId: oNode.key,
              })
            })
        ).then((resAll) => {
          let childNodes = []
          resAll.forEach((res, index) => {
            oNodes = oNodes.filter((oNode) => {
              return this.defaultExpandedKeys.indexOf(oNode.key) > -1
            })
            oNodes[index].children = this.parseTreeData(
              res.data,
              oNodes[index].fullpath,
              defaultExpandedKeys
            )
            childNodes = childNodes.concat(oNodes[index].children)
          })
          if (resAll.length !== 0) {
            if (defaultExpandedKeys.length !== 0) {
              this.loadBeforeExpand(childNodes, defaultExpandedKeys).then(() => {
                resolve()
              })
            } else {
              resolve()
            }
          }
        })
      })
    },
    loadExpand(oNodes, level) {
      // 默认加载并展开对应层的树
      return new Promise((resolve) => {
        let ids = []
        Promise.all(
          oNodes.map((oNode) => {
            return NavService.getTreeChild({
              productMode: true,
              parentId: oNode.key,
            })
          })
        ).then((resAll) => {
          let childNodes = []
          resAll.forEach((res, index) => {
            oNodes[index].children = this.parseTreeData(res.data, oNodes[index].fullpath)
            ids = ids.concat(
              res.data.map((item) => {
                return item.id
              })
            )
            childNodes = childNodes.concat(oNodes[index].children)
          })
          if (level > 0) {
            this.loadExpand(childNodes, level - 1).then((childIds) => {
              resolve(ids.concat(childIds))
            })
          } else {
            resolve(ids)
          }
        })
      })
    },

    parseTreeData(deps, fullpath, expandedKeys) {
      return deps.map((dep, index) => {
        if (expandedKeys) {
          const indexExpand = expandedKeys.indexOf(dep.id)
          if (indexExpand > -1) {
            expandedKeys.splice(indexExpand, 1)
          }
        }

        return {
          key: dep.id,
          title: dep.text,
          isLeaf: dep.leaf,
          fullpath: [...fullpath, index],
          scopedSlots: {
            title: 'title',
          },
        }
      })
    },
    refresh() {
      this.onLoadTreeData().then(() => {
        this.updateKey++
      })
    },
    updateRoot(name) {
      this.treeData[0].title = name
    },
    getGroupId(record) {
      let treeNodeParent = this.treeData[0]
      const nodeAuthList = this.hieraInfo?.nodeAuthList
      let groupIds = [-1]
      if (this.hieraInfo?.nodeAuthList.length > 0) {
        record.fullpath.forEach((item, index) => {
          if (index !== 0) {
            treeNodeParent = treeNodeParent.children[item]
            nodeAuthList.some((nodeAuth) => {
              if (nodeAuth.nodeId === treeNodeParent.key) {
                groupIds = groupIds.concat(nodeAuth.operCode)
                return true
              }
            })
          }
        })
      }
      return groupIds
    },
  },
}
</script>

<style module lang="scss">
@use '@/common/design' as *;
.spin {
  width: 100%;
  line-height: 10;
}
.treewrap {
  height: 100%;
  :global(.ant-input-search) {
    overflow: hidden;
  }
  :global(.ant-tree) {
    // height: calc(100% - 2 * #{$padding-md});
    height: 100%;
    overflow: auto;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  :global(.ant-card-body) {
    height: 100%;
    background: $white;
  }
  .active {
    color: $primary-color;
  }
  :global(.ant-tree.ant-tree-block-node li .ant-tree-node-content-wrapper) {
    width: auto;
  }
}
</style>
