<script lang="ts">
    import type { RouteLocationNormalizedLoaded } from 'vue-router'
    import { computed, defineComponent, reactive, ref, toRefs, unref, watch } from 'vue'
    import { useRouter } from 'vue-router'
    import type { MenuState } from './types'
    import type { Menu as MenuType } from '/@/router/types'
    import { useDesign } from '/@/hooks/web/useDesign'
    import Menu from './components/Menu.vue'
    import SimpleSubMenu from './SimpleSubMenu.vue'
    import { listenerRouteChange } from '/@/logics/mitt/routeChange'
    import { propTypes } from '/@/utils/propTypes'
    import { REDIRECT_NAME } from '/@/router/constant'
    import { isFunction, isUrl } from '/@/utils/is'
    import { openWindow } from '/@/utils'

    import { useOpenKeys } from './useOpenKeys'

    export default defineComponent({
        name: 'SimpleMenu',
        components: {
            Menu,
            SimpleSubMenu,
        },
        inheritAttrs: false,
        props: {
            items: {
                type: Array as PropType<MenuType[]>,
                default: () => [],
            },
            collapse: propTypes.bool,
            mixSider: propTypes.bool,
            theme: propTypes.string,
            accordion: propTypes.bool.def(true),
            collapsedShowTitle: propTypes.bool,
            beforeClickFn: {
                type: Function as PropType<(key: string) => Promise<boolean>>,
            },
            isSplitMenu: propTypes.bool,
        },
        emits: ['menuClick'],
        setup(props, { attrs, emit }) {
            const currentActiveMenu = ref('')
            const isClickGo = ref(false)

            const menuState = reactive<MenuState>({
                activeName: '',
                openNames: [],
                activeSubMenuNames: [],
            })

            const { currentRoute } = useRouter()
            const { prefixCls } = useDesign('simple-menu')
            const { items, accordion, mixSider, collapse } = toRefs(props)

            const { setOpenKeys, getOpenKeys } = useOpenKeys(menuState, items, accordion, mixSider, collapse)

            const getBindValues = computed(() => ({ ...attrs, ...props }))

            watch(
                () => props.collapse,
                (collapse) => {
                    if (collapse) {
                        menuState.openNames = []
                    } else {
                        setOpenKeys(currentRoute.value.path)
                    }
                },
                { immediate: true },
            )

            watch(
                () => props.items,
                () => {
                    if (!props.isSplitMenu) {
                        return
                    }
                    setOpenKeys(currentRoute.value.path)
                },
                { flush: 'post' },
            )

            listenerRouteChange((route) => {
                if (route.name === REDIRECT_NAME) return

                currentActiveMenu.value = route.meta?.currentActiveMenu as string
                handleMenuChange(route)

                if (unref(currentActiveMenu)) {
                    menuState.activeName = unref(currentActiveMenu)
                    setOpenKeys(unref(currentActiveMenu))
                }
            })

            async function handleMenuChange(route?: RouteLocationNormalizedLoaded) {
                if (unref(isClickGo)) {
                    isClickGo.value = false
                    return
                }
                const path = (route || unref(currentRoute)).path

                menuState.activeName = path

                setOpenKeys(path)
            }

            async function handleSelect(key: string) {
                if (isUrl(key)) {
                    openWindow(key)
                    return
                }
                const { beforeClickFn } = props
                if (beforeClickFn && isFunction(beforeClickFn)) {
                    const flag = await beforeClickFn(key)
                    if (!flag) return
                }

                emit('menuClick', key)

                isClickGo.value = true
                setOpenKeys(key)
                menuState.activeName = key
            }

            return {
                prefixCls,
                getBindValues,
                handleSelect,
                getOpenKeys,
                ...toRefs(menuState),
            }
        },
    })
</script>

<template>
    <Menu
        v-bind="getBindValues"
        :activeName="activeName"
        :openNames="getOpenKeys"
        :class="prefixCls"
        :activeSubMenuNames="activeSubMenuNames"
        @select="handleSelect"
    >
        <template v-for="item in items" :key="item.path">
            <SimpleSubMenu :item="item" :parent="true" :collapsedShowTitle="collapsedShowTitle" :collapse="collapse" />
        </template>
    </Menu>
</template>

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