<template>
  <div
    :class="[
      $style.wrapper,
      {
        [$style.single]: single,
      },
    ]"
  >
    <a-spin ref="scroll" :spinning="!dataLoaded" :class="$style.spin">
      <a-dropdown
        v-if="dataLoaded"
        v-model="showMenu"
        :get-popup-container="() => this.$refs.scroll.$el"
        :trigger="['contextmenu']"
        :disabled="single"
        @visibleChange="menuVisibleChange"
      >
        <div>
          <a-tree
            v-if="treeData"
            v-model="checkedKeys"
            :load-data="onLoadData"
            :tree-data="treeDataComputed"
            checkable
            :checked-keys="[...selectedKeys, ...targetKeys]"
            :default-expand-parent="true"
            :default-expanded-keys="expandedKeys"
            :selected-keys="[selectedNode && selectedNode.eventKey]"
            @click="treeClick"
            @click.native="treeClickNative"
            @dblclick="treeDblClick"
            @rightClick="treeRightClick"
            @contextmenu.native.capture="treeRightClickNative"
            @check="
              (_, props) => {
                onChecked(_, props, [...selectedKeys, ...targetKeys], itemSelect)
              }
            "
            @select="onSelect"
          />
        </div>
        <a-menu slot="overlay" @click="menuClick">
          <a-menu-item key="1" :disabled="!selectedNodeHasSelectableChild">
            <a-icon type="check" />选中下一级节点1
          </a-menu-item>
          <a-menu-item key="2" :disabled="!selectedNodeHasSelectableChild">
            <a-icon type="close" />取消下一级节点2
          </a-menu-item>
        </a-menu>
      </a-dropdown>
      <!-- 空span撑开加载条 -->
      <span></span>
    </a-spin>
    <a-empty v-if="dataLoaded && treeData.length === 0" :image="simpleImage" />
  </div>
</template>

<script>
import debounce from 'lodash.debounce'
import cloneDeep from 'lodash.clonedeep'
// import auditPermissionTreeService from '../audit-permission-tree-service'
import icTreeService from './ic-tree-service'
import components from './_import-components/ic-picker-source-tree-import'
import pickerSourceMixin from './picker-source-mixin'
import IcPickerLabel from './ic-picker-label'

function addDisableProp(data, targetKeys = []) {
  data.forEach((item) => {
    item.disabled = targetKeys.includes(item.key)
    if (item.children) {
      addDisableProp(item.children, targetKeys)
    }
  })
  return data
}

function isChecked(selectedKeys, eventKey) {
  return selectedKeys.indexOf(eventKey) !== -1
}

/**
 * SdValuePicker的数据源：树结构
 * @displayName SdPickerSourceTree 数据源-树结构
 */
export default {
  name: 'IcPickerSourceTree',
  components,
  mixins: [pickerSourceMixin],
  props: {
    /**
     * 根节点{code:'200000',name:'西安分公司'}
     */
    rootNode: {
      type: [Object, Array],
      default: undefined,
    },
    /**
     * <p>获取数据的回调，获取根节点时，parentId为undefined</p>
     * <pre>(parentId,parent) => childrenItems</pre>
     */
    loadTreeData: {
      type: Function,
      required: true,
    },
    /**
     * <p>搜索数据的回调</p>
     * <pre>(searchText) => items</pre>
     * @since 8.0.2
     */
    searchTreeData: {
      type: Function,
      default: undefined,
    },
    /**
     * 默认展开指定的树节点
     * @since 8.0.7
     */
    defaultExpandedKeys: {
      type: Array,
      default: undefined,
    },
    versionId: {
      type: String,
      default: '',
    },
    orgId: {
      type: String,
      default: '',
    },
    selecttype: {
      type: String,
      default: 'control',
    },
    types: {
      type: String,
      default: 'NK',
    },
    isAbandonment: {
      type: String,
      default: 'NO',
    },
    // moduleId: {
    //   type: String,
    //   default: undefined,
    // },
  },

  data() {
    return {
      treeData: null,
      searchValueDebounce: '',
      searchedData: [],
      expandedKeys: [],
      showMenu: false,
      selectedNode: undefined,
      dataList: [], // 数组dataList，搜索要用
      checkedKeys: { checked: [], halfChecked: [] }, // 选中的节点数据
      halfCheckedKeys: [],
      isendids: [],
    }
  },
  computed: {
    listOrTreeData() {
      return this.searchValueDebounce ? this.searchedData : this.treeData
    },
    treeDataComputed() {
      // targetKeys和disabledKeys中的都变成禁用状态
      return addDisableProp(this.listOrTreeData, this.targetKeys.concat(this.disabledKeys))
    },
    selectedNodeHasSelectableChild() {
      return this.selectedNode?.dataRef.children?.some((item) => item.checkable && !item.disabled)
    },
  },
  watch: {
    listOrTreeData(data) {
      // 把treeData中所有selectable的节点，转成一个列表，给父组件作为dataSource
      const result = []
      function flatten(list, that) {
        list = list ?? []
        list.forEach((item) => {
          if (item.checkable) {
            result.push(item.originalValue)
          }

          flatten(item.children, that)
        })
      }
      flatten(data, this)
      this.updateDataSource(result)
    },
    searchValue(text) {
      this.doSearch(text)
    },
  },
  created() {
    this.loadDataForRoot()
  },
  methods: {
    transformData(data) {
      return data.map((d) => {
        const { children, checkable, selectable, isLeaf, ...rest } = d
        return {
          ...rest,
          checkable: checkable ?? true,
          selectable: selectable ?? false,
          isLeaf: isLeaf ?? true,
          key: d[this.optionValue],
          title: <IcPickerLabel vnodes={this.render(d, 'left')} />,
          children: children && this.transformData(children),
          originalValue: rest,
          code: rest.code,
        }
      })
    },
    loadDataForRoot() {
      Promise.resolve(this.loadTreeData())
        .then((data) => {
          if (this.selecttype === 'cross') {
            data.forEach((i) => {
              if (i.children) {
                i.children.forEach((c) => {
                  if (c.props.isEnd === '0') {
                    c.isLeaf = false
                    c.cat = true
                  } else {
                    c.cat = false
                    this.isendids.push(c.id.toString())
                  }
                })
              }
            })
          }
          this.treeData = this.transformData(data)
          if (this.defaultExpandedKeys) {
            this.expandedKeys = this.defaultExpandedKeys
          } else {
            // 没传展开的keys，根节点只有一个的话，展开它
            if (this.treeData.length === 1) {
              this.expandedKeys = [this.treeData[0].key]
            }
          }
        })
        .finally(() => (this.dataLoaded = true))
    },
    loadData(treeNode) {
      return new Promise((resolve) => {
        if (treeNode.dataRef.children) {
          // 有值了直接渲染
          resolve()
          return
        }
        Promise.resolve(
          this.loadTreeData(treeNode.dataRef.oldId, cloneDeep(treeNode.dataRef.originalValue))
        ).then((data) => {
          treeNode.dataRef.children = this.transformData(data)
          if (this.searchValueDebounce) {
            this.searchedData = [...this.searchedData]
          } else {
            this.treeData = [...this.treeData]
          }

          resolve()
        })
      })
    },
    doSearch(text) {
      this.searchValueDebounce = text
      if (!text) return
      this.dataLoaded = false
      this.searchedData = []
      Promise.resolve(this.searchTreeData(text))
        .then((data) => {
          // 返回一个列表，转换成树的格式
          this.searchedData = this.transformData(data)
        })
        .finally(() => (this.dataLoaded = true))
    },
    onChecked(_, e, checkedKeys, itemSelect) {
      const { eventKey } = e.node
      if (this.single) {
        // 单选模式，取消已经选中的，再选中当前的
        if (!isChecked(checkedKeys, eventKey)) {
          itemSelect(checkedKeys[0], false)
          itemSelect(eventKey, true)
        }
      } else {
        itemSelect(eventKey, !isChecked(checkedKeys, eventKey))
        if (this.selecttype === 'cross') {
          this.halfCheckedKeys = _.filter((i) => this.isendids.indexOf(i) === -1)
          // this.halfCheckedKeys = _.filter((i) => i.indexOf('1000') === -1)
        } else {
          this.halfCheckedKeys = _.filter((i) => i.indexOf('1000') === -1)
        }
      }
    },
    treeClick(evt, treeNode) {
      const nodeData = treeNode.dataRef
      if (nodeData.disabled) return
      // 非叶子节点 + 不可选中，展开节点
      if (!nodeData.isLeaf && !nodeData.checkable && !nodeData.selectable)
        treeNode.vcTree.onNodeExpand(evt, treeNode)
    },
    treeDblClick(evt, treeNode) {
      const nodeData = treeNode.dataRef
      if (nodeData.disabled) return
      if (nodeData.checkable) this.itemDblClick(evt, nodeData.key)
    },
    treeClickNative() {
      // 点击树的其他区域，隐藏菜单
      if (this.single) return
      this.hideContextMemu()
    },
    treeRightClick({ node }) {
      // 记录当前点击的节点
      if (this.single) return
      this.selectedNode = node
    },
    hideContextMemu() {
      this.showMenu = false
      this.menuVisibleChange(false)
    },
    menuVisibleChange(visible) {
      if (!visible) this.selectedNode = undefined
    },
    treeRightClickNative(evt) {
      // 右键如果没有点击到树节点，不触发右键菜单
      if (this.single) return
      if (evt.target.nodeName !== 'SPAN') evt.stopPropagation()
    },
    menuClick(menu) {
      this.selectedNode.dataRef.children?.forEach((item) => {
        if (item.checkable && !item.disabled) this.itemSelect(item.key, menu.key === '1')
      })
      this.hideContextMemu()
    },
    onSelect(selectedKeys, evt) {
      /**
       * 树节点的选中事件
       * @property {Object} treeItem 选中的节点
       * @property {Object} evt 其他信息{selected: bool, selectedNodes, node, event}
       */
      this.$emit('treeItemSelect', { ...evt.node.dataRef.originalValue }, evt)
    },
    // 点击地址树展开时调用
    onLoadData(treeNode) {
      const params = {
        auditOrgId: parseInt(this.orgId),
        versionId: parseInt(this.versionId),
        isAbandonment: this.isAbandonment,
      }
      if (this.selecttype === 'cross') {
        return icTreeService
          .getCategoryTree(treeNode.dataRef.id, params, this.types)
          .then((res) => {
            if (treeNode.dataRef.children !== null && treeNode.dataRef.children.length > 0) {
              console.log('有子节点，不请求')
            } else {
              res.data.forEach((item) => {
                item.code = item.id.toString()
                if (item.props.isEnd === '0') {
                  item.isLeaf = false
                  item.cat = true
                } else {
                  item.cat = false
                  this.isendids.push(item.id.toString())
                }
              })
              treeNode.dataRef.children = this.transformData(res.data)
              this.treeData = [...this.treeData]
            }
          })
      } else {
        return icTreeService.getMeasureTree(treeNode.dataRef.id, params, this.types).then((res) => {
          if (treeNode.dataRef.children !== null && treeNode.dataRef.children.length > 0) {
            console.log('有子节点，不请求')
          } else {
            res.data.forEach((item) => {
              item.code = item.id.toString()
              if (item.props.disabled) {
                item.isLeaf = false
                item.cat = true
              } else {
                item.cat = false
              }
            })
            treeNode.dataRef.children = this.transformData(res.data)
            this.treeData = [...this.treeData]
          }
        })
      }
    },
    // 初始化地址树
    initTreeData(depId) {
      const topDepId = -1
      const params = {
        auditOrgId: 521,
        versionId: 341,
      }
      icTreeService.getCategoryTree(topDepId, params).then((res1) => {
        this.spinning = false
        const treeNode = res1.data
        this.treeData = this.transformData(treeNode)
        this.expandedKeys = this.defaultTreeExpandedKeys
        this.generateList(this.treeData)
        this.empty = false
        this.dataLoaded = true
      })
    },

    // 处理搜索用的dataList
    generateList(data) {
      for (let i = 0; i < data.length; i++) {
        const node = data[i]
        const key = node.id
        const title = node.text
        const props = node.props
        this.dataList.push({ key, id: key, title: title, props })
        if (node.children) {
          this.generateList(node.children)
        }
      }
    },
  },
}
</script>

<style module lang="scss">
@use '@/common/design' as *;
@import './source.scss';

.wrapper {
  :global .ant-tree-title {
    user-select: none;
    overflow: hidden;
    text-overflow: ellipsis;
    width: 200px;
    display: block;
  }
}
.single {
  :global .ant-tree-checkbox {
    .ant-tree-checkbox-inner {
      border-radius: 100px;
      &::after {
        position: absolute;
        top: 3px;
        left: 3px;
        display: table;
        width: 8px;
        height: 8px;
        content: ' ';
        background-color: $primary-color;
        border: 0;
        border-radius: 8px;
        opacity: 0;
        transition: all 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
        transform: scale(0);
      }
    }
    &.ant-tree-checkbox-checked {
      &::after {
        position: absolute;
        top: 16.67%;
        left: 0;
        width: 100%;
        height: 66.67%;
        content: '';
        border: 1px solid #1890ff;
        border-radius: 50%;
        animation: antRadioEffect 0.36s ease-in-out;
        animation-fill-mode: both;
      }
      .ant-tree-checkbox-inner {
        background-color: $white;
        &::after {
          opacity: 1;
          transition: all 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
          transform: scale(1);
        }
      }
    }
  }
}
</style>

<docs>
需要作为 [SdValuePicker](#sdvaluepicker) 的子节点使用，样例请参考 [SdValuePicker](#sdvaluepicker)
</docs>
