<script setup>
import { nanoid } from 'nanoid'

const { maxNum } = defineProps({
  maxNum: {
    type: Number,
    default: 3,
  },
})

const wrap = ref(null)
const dropdown = ref(null)
const dropdownMenu = ref(null)
let isMenuObserve = false // dropdown菜单是否被监听
const dropdownItems = ref(null)
const vm = getCurrentInstance().proxy
const mutationLock = ref(false) // 防止死循环

// 挂载时
onMounted(async () => {
  handleChildrenVisible()
  mutationObserve(wrap.value)
})

// 监听dom元素改变
function mutationObserve(el) {
  const config = {
    attributes: false,
    childList: true,
    subtree: true,
  }
  const observer = new MutationObserver(handleMutaionCallback)
  observer.observe(el, config)
  return observer
}

// 监听回调
function handleMutaionCallback(mutationsList, observer) {
  // debugger
  if (mutationLock.value) return
  for (let m of mutationsList) {
    if (m.type === 'childList') {
      if (m.removedNodes.length > 0 || m.addedNodes.length > 0) {
        Promise.resolve().then(handleChildrenVisible)
        break
      }
    }
  }
}

const visibleDropdown = ref(false)
const menuList = ref([])
let menuObserver = null
// 最多显示3个按钮
async function handleChildrenVisible() {
  if (!wrap.value) return
  mutationLock.value = true
  const eleChildren = vm.$slots.default
  // 可见子节点的数量
  const visibleChidren = eleChildren.filter(item => item.tag && item?.elm?.style?.display !== 'none')
  // console.log(visibleChidren)
  // 矫正dom顺序
  eleChildren.forEach((item) => {
    wrap.value.appendChild(item.elm)
  })
  // console.log(eleChildren)
  // debugger
  if (visibleChidren.length > maxNum) {
    visibleDropdown.value = true
    const btnLen = eleChildren.length
    menuList.value = Array.from({ length: btnLen - maxNum + 1  }).fill(0).map(v => ({ id: nanoid() }))
    await nextTick()
    // 监听dropdownMenu的dom变化
    if (!isMenuObserve) {
      menuObserver = mutationObserve(dropdownMenu.value.$el)
      isMenuObserve = true
    }
    dropdownItems.value?.forEach((item, idx) => {
      const { elm, tag } = eleChildren[maxNum - 1 + idx]
      item.appendChild(elm)
      const display = elm?.style?.display
      item.style.display = (tag && display !== 'none') ? 'block' : 'none'
    })
  } else {
    eleChildren.forEach((item) => {
      wrap.value.appendChild(item.elm)
    })
    visibleDropdown.value = false
    isMenuObserve = false
    menuObserver?.disconnect()
    menuObserver = null
  }
  await nextTick()
  mutationLock.value = false
}

// 隐藏菜单
function hideMenu() {
  dropdown.value.hide()
}

</script>

<template>
  <div>
    <div style="display: inline-block;" ref="wrap"><slot></slot></div>
    <keep-alive>
      <el-dropdown ref="dropdown" v-if="visibleDropdown" trigger="hover" :show-timeout="200" :hide-on-click="false">
        <slot name="button">
          <el-button type="text" class="ml-12px">更多</el-button>
        </slot>
        <el-dropdown-menu
          slot="dropdown"
          ref="dropdownMenu"
          class="minw-40px dropdown-menu-wrap"
          @click.capture.passive.native="hideMenu"
        >
          <li class="li-dropdown-item" ref="dropdownItems" v-for="item in menuList" :key="item.id"></li>
        </el-dropdown-menu>
      </el-dropdown>
    </keep-alive>
  </div>
</template>

<style lang="scss" scoped>
.dropdown-menu-wrap ::v-deep {
  .el-dropdown-menu__item {
    padding: 0;
    .el-button {
      width: 100%;
      text-align: left;
      padding: 0 12px;
    }
  }
  .li-dropdown-item {
    display: flex;
    height: 28px;
    line-height: 28px;
    &:hover {
      background-color: var(--color-blue1);
    }
    .el-button {
      width: 100%;
      text-align: left;
      padding: 0 12px;
    }
  }
}
</style>
