<template>
  <div>
    <portal to="top-nav-menu">
      <a-menu v-model="currentTopCate" :class="$style.topMenu" mode="horizontal">
        <a-menu-item
          v-for="subMenu in topMenu.slice(0, menuShowNum)"
          :key="subMenu.id"
          @click="
            (menu) => {
              if (!currentTopCate.includes(menu.key)) {
                itemClick(subMenu)
              }
            }
          "
        >
          <a-tooltip :title="subMenu.title">
            <a-icon
              v-if="subMenu.icon"
              :type="subMenu.icon"
              :theme="subMenu.icon.indexOf('-audit-') > 0 ? 'filled' : 'outlined'"
            />{{ subMenu.title }}
          </a-tooltip>
        </a-menu-item>
        <a-sub-menu
          v-if="topMenu.length > menuShowNum"
          :popup-class-name="topMenu.length - menuShowNum > 4 ? $style.flexChild : ''"
          ><span slot="title" class="submenu-title-wrapper"
            ><a-icon type="sd-appstore" />更多应用</span
          >
          <a-menu-item
            v-for="subMenu in topMenu.slice(menuShowNum)"
            :key="subMenu.id"
            @click="itemClick(subMenu)"
          >
            <a-tooltip :title="subMenu.title">
              <a-icon
                v-if="subMenu.icon"
                :type="subMenu.icon"
                :theme="subMenu.icon.indexOf('-audit-') > 0 ? 'filled' : 'outlined'"
              />{{ subMenu.title }}
            </a-tooltip>
          </a-menu-item>
        </a-sub-menu>
      </a-menu>
    </portal>
    <a-menu
      mode="inline"
      :selected-keys="current"
      :open-keys.sync="openKeysForTemplate"
      theme="dark"
    >
      <template v-for="subMenu in menu">
        <a-menu-item
          v-if="subMenu.children.length === 0"
          :key="subMenu.id"
          @click="itemClick(subMenu)"
        >
          <a-icon
            v-if="subMenu.icon"
            :type="subMenu.icon"
            :theme="subMenu.icon.indexOf('-audit-') > 0 ? 'filled' : 'outlined'"
          />
          <span :title="subMenu.title">{{ subMenu.title }}</span>
          <trustMenus
            :trust-menus="subMenu.trustMenus"
            :class="$style.trust"
            @click="(item) => itemClick(item)"
          />
        </a-menu-item>
        <a-sub-menu
          v-else
          :key="subMenu.id"
          :class="{ 'ant-menu-item-selected': current[0] === subMenu.id }"
          @titleClick="
            (menu) => {
              if (!openKeys.includes(menu.key)) {
                itemClick(subMenu)
              }
            }
          "
        >
          <span slot="title">
            <a-icon
              v-if="subMenu.icon"
              :type="subMenu.icon"
              :theme="subMenu.icon.indexOf('-audit-') > 0 ? 'filled' : 'outlined'"
            /><span :title="subMenu.title">{{ subMenu.title }}</span>
          </span>
          <template v-for="item in subMenu.children">
            <a-menu-item v-if="item.children.length === 0" :key="item.id" @click="itemClick(item)">
              <span :title="item.title">{{ item.title }}</span>
              <!-- 兼职的 -->
              <trustMenus
                :trust-menus="item.trustMenus"
                :class="$style.trust"
                @click="(item) => itemClick(item)"
              />
            </a-menu-item>
            <a-menu-item v-else :key="item.id">
              <a-popover
                :visible="show[item.id] && show[item.id].visible"
                placement="rightTop"
                overlay-class-name="sd-nav-menu-popover"
                @visibleChange="(falg) => visibleChange(falg, item.id)"
              >
                <a :class="$style.amenu" size="small">
                  {{ item.title }} <a-icon type="sd-right" />
                </a>
                <a-menu slot="content" theme="dark" :class="$style.dropmenu">
                  <!-- 先支持到四级 -->
                  <template v-for="citem in item.children">
                    <!-- v-for="citem in item.children" -->
                    <a-menu-item
                      v-if="citem.children.length === 0"
                      :key="citem.id"
                      @click="itemClick(citem)"
                    >
                      <span>{{ citem.title }}</span>
                      <!-- 兼职的 -->
                      <a-dropdown
                        v-if="citem.trustMenus"
                        :visible="show[item.id] && show[item.id].visible2"
                        :class="$style.trust"
                        @visibleChange="(flag) => visibleChange2(flag, item.id)"
                      >
                        <a><a-icon type="usergroup-add"/></a>
                        <a-menu slot="overlay">
                          <a-menu-item
                            v-for="itm2 in citem.trustMenus"
                            :key="itm2.srcTrustId"
                            @click="itemClick(itm2)"
                          >
                            {{ itm2.text }}
                          </a-menu-item>
                        </a-menu>
                      </a-dropdown>
                    </a-menu-item>
                    <!-- 先支持到五级 -->
                    <a-menu-item v-else :key="citem.id">
                      <a-popover
                        :visible="show[citem.id] && show[citem.id].visible"
                        placement="rightTop"
                        overlay-class-name="sd-nav-menu-popover"
                        @visibleChange="(falg) => visibleChange(falg, citem.id)"
                      >
                        <a :class="$style.amenu" size="small">
                          {{ citem.title }} <a-icon type="sd-right" />
                        </a>
                        <a-menu
                          slot="content"
                          theme="dark"
                          :class="['sdnavczmenu', $style.dropmenu]"
                        >
                          <a-menu-item
                            v-for="czitem in citem.children"
                            :key="czitem.id"
                            @click="itemClick(czitem)"
                          >
                            <span>{{ czitem.title }}</span>
                            <!-- 兼职的 -->
                            <a-dropdown
                              v-if="czitem.trustMenus"
                              :visible="show[citem.id] && show[citem.id].visible2"
                              :class="$style.trust"
                              @visibleChange="(flag) => visibleChange2(flag, citem.id)"
                            >
                              <a><a-icon type="usergroup-add"/></a>
                              <a-menu slot="overlay">
                                <a-menu-item
                                  v-for="itm3 in czitem.trustMenus"
                                  :key="itm3.srcTrustId"
                                  @click="itemClick(itm3)"
                                >
                                  {{ itm3.text }}
                                </a-menu-item>
                              </a-menu>
                            </a-dropdown>
                          </a-menu-item>
                        </a-menu>
                      </a-popover>
                    </a-menu-item>
                  </template>
                </a-menu>
              </a-popover>
            </a-menu-item>
          </template>
        </a-sub-menu>
      </template>
      <a-menu-item v-if="loading" key="loading" :class="$style.loading">
        <a-icon type="loading" />
        <span>加载中……</span>
      </a-menu-item>
    </a-menu>
  </div>
</template>

<script>
import Vue from 'vue'
import { Menu, Tooltip } from 'ant-design-vue'
import openAsTrustId from '@/common/services/open-as-trust-id'
import loginService from '@/login/login-service'
import { sdLocalStorage } from '@/common/services/storage-service'
import navMenuService from './nav-menu-service'

Vue.use(Menu)
Vue.use(Tooltip)

export default {
  name: 'SdNavMenu',
  components: {
    trustMenus: {
      props: ['trustMenus'],
      render() {
        if (this.trustMenus) {
          return (
            <a-dropdown>
              <a>
                <a-icon type='usergroup-add' />
              </a>
              <a-menu slot='overlay'>
                {this.trustMenus.map((item) => {
                  return (
                    <a-menu-item key={item.srcTrustId} vOn:click={() => this.$emit('click', item)}>
                      {item.text}
                    </a-menu-item>
                  )
                })}
              </a-menu>
            </a-dropdown>
          )
        }
      },
    },
  },
  props: {
    collapsed: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      loading: true,
      currentTopCate: [],
      current: [],
      openKeys: [],
      openKeysCollapsed: [],
      topMenu: [],
      menuShowNum: 0,
      screenWidth: document.documentElement.clientWidth,
      show: {},
    }
  },
  computed: {
    menu() {
      // 根据顶级分类过滤左侧菜单项
      return this.topMenu
        .find((sub) => sub.id === this.currentTopCate[0])
        ?.children?.filter(
          (item) => !item.props.workbench || navMenuService.getWorkBench().url === item.url
        )
    },
    openKeysForTemplate: {
      get: function() {
        return this.collapsed ? this.openKeysCollapsed : this.openKeys
      },
      set: function(keys) {
        if (this.collapsed) {
          this.openKeysCollapsed = keys
        } else {
          this.openKeys = keys
        }
      },
    },
  },
  watch: {
    $route(route) {
      this.handleRouteChange(route)
    },
    menu(menu) {
      // 从当前的菜单中，寻找已经展开的分类+选中的分类
      const haveOpenCate = [...this.openKeys, ...this.current].some((key) => {
        return menu.some((subMenu) => {
          return subMenu.id === key
        })
      })
      // 没找到任何已展开的分类的话，且只有个子分类，展开第一个分类
      if (!haveOpenCate) {
        const firstHasChild = menu.find((subMenu) => subMenu.children?.length > 0)
        if (firstHasChild && menu.length === 1) this.openKeys.push(firstHasChild.id)
      }
    },
    screenWidth(newVal) {
      this.screenWidth = newVal
      this.getMenuShowNum()
    },
  },
  mounted() {
    window.addEventListener('resize', this.listenResize)
  },
  created() {
    navMenuService.fetch().then((data) => {
      this.loading = false
      this.topMenu = data.menuTreeNodes
      this.$emit('naviGroupsUpdated', data.otherMenuGroups)
      // 找到当前url对应的菜单项
      this.handleRouteChange(this.$route)
      this.$nextTick(() => {
        this.getMenuShowNum()
      })
    })
  },
  methods: {
    getMenuShowNum() {
      const headerWidth =
        document.getElementsByClassName('right_sd-header_common')[0].offsetWidth - 20
      const triggerWidth = document.getElementsByClassName('trigger_sd-frame_frame')[0].offsetWidth
      // const toolsWidth = document.getElementsByClassName('tools_sd-frame_frame')[0]?.offsetWidth
      const toolsWidth = 0
      this.menuShowNum = Math.floor((headerWidth - triggerWidth - toolsWidth) / 130) - 1
    },
    listenResize() {
      this.screenWidth = document.documentElement.clientWidth
    },
    itemClick(item) {
      console.log(item)
      item.target = item.target || '_blank'
      let url = item.url
      if (item.url?.startsWith('/sd-ssologin')) {
        loginService.updateAccessToken().then(() => {
          const sysManageUrl = JSON.parse(sdLocalStorage.getItem('commonConfig') || '{}')
            .weSysManage?.sysManageUrl
          url =
            url.replace('/sd-ssologin', 'api/ssologin').replace('{admin_server}', sysManageUrl) +
            '&token=' +
            loginService.getTokens().access_token.replace('Bearer ', '')
          const newWindow = window.open(url, item.target)
          newWindow.opener = null
        })
        return
      }
      // http开头的新窗口打开
      if (item.url?.startsWith('http')) {
        const newWindow = window.open(url, item.target)
        newWindow.opener = null
        return
      }
      if (url) {
        openAsTrustId(url, item.srcTrustId)
        navMenuService.recordMenuClick({ menuId: item.menuId })
      }
    },
    handleRouteChange(route) {
      if (this.$route.path === '/sd-frame') {
        const item = navMenuService.getWorkBench()
        if (item.url.startsWith('/sd-ssologin')) {
          // 把被单点链接配置成了默认进入的页面
          this.itemClick(item)
        } else {
          this.$router.replace(item.url)
        }
        return
      }
      const [
        topCate = this.currentTopCate?.[0] || this.topMenu[0].id,
        cate,
        current,
      ] = navMenuService.getSelectedItem(route.fullPath)
      this.currentTopCate = [topCate]
      if (cate && !this.openKeys.includes(cate)) this.openKeys.push(cate)
      this.current = [current]
      // 一个nextTick不工作，两个可以
      this.$nextTick(() => {
        this.$nextTick(() => {
          this.$el.querySelector('.ant-menu-item-selected')?.scrollIntoViewIfNeeded?.()
        })
      })
    },
    visibleChange(flag, id) {
      // 两个dorpmenu显示联动处理，如果最后一个dropmenu还显示，上一个就不隐藏
      if (!this.show[id]) {
        this.show[id] = {}
      }
      this.show[id].visible = flag
      if (this.show[id].visible2) {
        this.show[id].visible = true
      }
      this.show = { ...this.show }
    },
    visibleChange2(flag, id) {
      if (!this.show[id]) {
        this.show[id] = {}
      }
      this.show[id].visible2 = flag
      // 第二个隐藏了第一个也隐藏掉
      if (!flag) {
        this.show[id].visible = false
      }
      this.show = { ...this.show }
    },
  },
}
</script>

<style module lang="scss">
@use '@/common/design' as *;
.loading {
  pointer-events: none;
}

[role='menu'].top-menu {
  display: inline-block;
  font-weight: 600;
  line-height: inherit;
  vertical-align: top;
  background: transparent;
  li[role='menuitem'] {
    top: 0;
    width: 130px;
    padding: 0;
    overflow: hidden;
    color: $text-color-inverse;
    text-align: center;
    text-overflow: ellipsis;
    border: none;
  }
  :global(.ant-menu-item-selected),
  :global(.ant-menu-submenu-selected),
  li[role='menuitem']:hover {
    // 选中的颜色，与主题无关
    /* stylelint-disable-next-line */
    background-color: rgba(0, 0, 0, 0.2);
    :global(.ant-menu-submenu-title:hover) {
      color: $text-color-inverse;
    }
  }
}
:global(.sd-nav-menu-popover) {
  :global(.ant-popover-arrow) {
    display: none;
  }
  :global(.ant-popover-inner-content) {
    max-height: 100vh;
    padding: 0 0 0 5px;
    overflow-y: scroll;
  }
  :global(.ant-popover-inner) {
    background: transparent;
    border: none;
    box-shadow: none;
  }
  [role='menu'] {
    width: auto;
    border-radius: 4px;
  }
  [role='menuitem'] {
    position: relative;
  }
}
a.trust {
  position: absolute;
  top: 0;
  right: 0;
  margin: 0;
}

.amenu i {
  &:global(.anticon-sd-right) {
    float: right;
    margin: 0;
    font-size: 0.8em;
    line-height: 3.3;
  }
}
.flex-child {
  > ul {
    display: flex;
    flex-wrap: wrap;
    max-width: 530px;
    &:global(.ant-menu-vertical) {
      padding: 10px;
    }
    > :global(.ant-menu-item) {
      width: 25%;
    }
  }
}
</style>
