<script lang="ts">
    import type { MenuState } from './types'
    import { computed, defineComponent, reactive, ref, toRefs, unref, watch } from 'vue'
    import { Menu } from 'ant-design-vue'
    import BasicSubMenuItem from './components/BasicSubMenuItem.vue'
    import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum'
    import { useOpenKeys } from './useOpenKeys'
    import type { RouteLocationNormalizedLoaded } from 'vue-router'
    import { useRouter } from 'vue-router'
    import { isFunction } from '/@/utils/is'
    import { basicProps } from './props'
    import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'
    import { REDIRECT_NAME } from '/@/router/constant'
    import { useDesign } from '/@/hooks/web/useDesign'
    import { getCurrentParentPath } from '/@/router/menus'
    import { listenerRouteChange } from '/@/logics/mitt/routeChange'
    import { getAllParentPath } from '/@/router/helper/menuHelper'

    export default defineComponent({
        name: 'BasicMenu',
        components: {
            Menu,
            BasicSubMenuItem,
        },
        props: basicProps,
        emits: ['menuClick'],
        setup(props, { emit }) {
            const isClickGo = ref(false)
            const currentActiveMenu = ref('')

            const menuState = reactive<MenuState>({
                defaultSelectedKeys: [],
                openKeys: [],
                selectedKeys: [],
                collapsedOpenKeys: [],
            })

            const { prefixCls } = useDesign('basic-menu')
            const { items, mode, accordion } = toRefs(props)

            const { getCollapsed, getTopMenuAlign, getSplit } = useMenuSetting()

            const { currentRoute } = useRouter()

            const { handleOpenChange, setOpenKeys, getOpenKeys } = useOpenKeys(menuState, items, mode as any, accordion)

            const getIsTopMenu = computed(() => {
                const { type, mode } = props

                return (
                    (type === MenuTypeEnum.TOP_MENU && mode === MenuModeEnum.HORIZONTAL) ||
                    (props.isHorizontal && unref(getSplit))
                )
            })

            const getMenuClass = computed(() => {
                const align = props.isHorizontal && unref(getSplit) ? 'start' : unref(getTopMenuAlign)
                return [
                    prefixCls,
                    `justify-${align}`,
                    {
                        [`${prefixCls}__second`]: !props.isHorizontal && unref(getSplit),
                        [`${prefixCls}__sidebar-hor`]: unref(getIsTopMenu),
                    },
                ]
            })

            const getInlineCollapseOptions = computed(() => {
                const isInline = props.mode === MenuModeEnum.INLINE

                const inlineCollapseOptions: { inlineCollapsed?: boolean } = {}
                if (isInline) {
                    inlineCollapseOptions.inlineCollapsed = props.mixSider ? false : unref(getCollapsed)
                }
                return inlineCollapseOptions
            })

            listenerRouteChange((route) => {
                if (route.name === REDIRECT_NAME) return
                handleMenuChange(route)
                currentActiveMenu.value = route.meta?.currentActiveMenu as string

                if (unref(currentActiveMenu)) {
                    menuState.selectedKeys = [unref(currentActiveMenu)]
                    setOpenKeys(unref(currentActiveMenu))
                }
            })

            !props.mixSider &&
                watch(
                    () => props.items,
                    () => {
                        handleMenuChange()
                    },
                )

            async function handleMenuClick({ key }: { key: string; keyPath: string[] }) {
                const { beforeClickFn } = props
                if (beforeClickFn && isFunction(beforeClickFn)) {
                    const flag = await beforeClickFn(key)
                    if (!flag) return
                }
                emit('menuClick', key)

                isClickGo.value = true
                menuState.selectedKeys = [key]
            }

            async function handleMenuChange(route?: RouteLocationNormalizedLoaded) {
                if (unref(isClickGo)) {
                    isClickGo.value = false
                    return
                }
                const path =
                    (route || unref(currentRoute)).meta?.currentActiveMenu || (route || unref(currentRoute)).path
                setOpenKeys(path)
                if (unref(currentActiveMenu)) return
                if (props.isHorizontal && unref(getSplit)) {
                    const parentPath = await getCurrentParentPath(path)
                    menuState.selectedKeys = [parentPath]
                } else {
                    const parentPaths = await getAllParentPath(props.items, path)
                    menuState.selectedKeys = parentPaths
                }
            }

            return {
                handleMenuClick,
                getInlineCollapseOptions,
                getMenuClass,
                handleOpenChange,
                getOpenKeys,
                ...toRefs(menuState),
            }
        },
    })
</script>

<template>
    <Menu
        :selectedKeys="selectedKeys"
        :defaultSelectedKeys="defaultSelectedKeys"
        :mode="mode"
        :openKeys="getOpenKeys"
        :inlineIndent="inlineIndent"
        :theme="theme"
        @open-change="handleOpenChange"
        :class="getMenuClass"
        @click="handleMenuClick"
        :subMenuOpenDelay="0.2"
        v-bind="getInlineCollapseOptions"
    >
        <template v-for="item in items" :key="item.path">
            <BasicSubMenuItem :item="item" :theme="theme" :isHorizontal="isHorizontal" />
        </template>
    </Menu>
</template>

<style lang="less">
    @import './index.less';
</style>
