/**
 * 该插件可根据菜单配置自动生成 ANTD menu组件
 * menuOptions示例：
 * [
 *  {
 *    name: '菜单名称',
 *    path: '菜单路由',
 *    meta: {
 *      icon: '菜单图标',
 *      invisible: 'boolean, 是否不可见, 默认 false',
 *    },
 *    children: [子菜单配置]
 *  },
 *  {
 *    name: '菜单名称',
 *    path: '菜单路由',
 *    meta: {
 *      icon: '菜单图标',
 *      invisible: 'boolean, 是否不可见, 默认 false',
 *    },
 *    children: [子菜单配置]
 *  }
 * ]
 *
 * i18n: 国际化配置。系统默认会根据 options route配置的 path 和 name 生成英文以及中文的国际化配置，如需自定义或增加其他语言，配置
 * 此项即可。如：
 * i18n: {
 *   messages: {
 *     zh_CN: {dashboard: {name: '监控中心'}}
 *
 *   }
 * }
 **/
import Menu from 'ant-design-vue/es/menu';
import Icon from 'ant-design-vue/es/icon';
import { getUserInfo } from '@/utils';
import { mapState } from 'vuex';

const { Item, SubMenu } = Menu;

export default {
    name: 'IMenu',
    props: {
        options: {
            type: Array,
            required: true,
        },
        theme: {
            type: String,
            required: false,
            default: 'dark',
        },
        mode: {
            type: String,
            required: false,
            default: 'inline',
        },
        collapsed: {
            type: Boolean,
            required: false,
            default: false,
        },
        i18n: Object,
    },
    data() {
        return {
            selectedKeys: [],
            sOpenKeys: [],
            cachedOpenKeys: [],
            menuData: [],
            allMenuList: [],
        };
    },
    computed: {
        ...mapState('settingModule', ['layout']),
        menuTheme() {
            return this.theme == 'light' ? this.theme : 'dark';
        },
    },
    created() {
        const { menuList } = getUserInfo();
        // 增加查询速度
        this.menuData = menuList.filter(i => i.menuType === 'MENU');
        this.allMenuList = menuList;
        this.updateMenu();
    },
    watch: {
        i18n(val) {
            if (val && val.messages) {
                const messages = this.i18n.messages;
                Object.keys(messages).forEach(key => {
                    this.$i18n.mergeLocaleMessage(key, messages[key]);
                });
            }
        },
        collapsed(val) {
            if (val) {
                this.cachedOpenKeys = this.sOpenKeys;
                this.sOpenKeys = [];
            } else {
                this.sOpenKeys = this.cachedOpenKeys;
            }
        },
        sOpenKeys(val) {
            this.$emit('openChange', val);
            this.$emit('update:openKeys', val);
        },
    },
    methods: {
        renderIcon(h, icon, key) {
            if (this.$scopedSlots.icon && icon && icon !== 'none') {
                const vnodes = this.$scopedSlots.icon({ icon, key });
                vnodes.forEach(vnode => {
                    vnode.data.class = vnode.data.class ? vnode.data.class : [];
                    vnode.data.class.push('anticon');
                });
                return vnodes;
            }
            return !icon || icon == 'none' ? null : h(Icon, { props: { type: icon } });
        },

        renderMenuItem(h, menu) {
            const tag = 'router-link';

            const config = {
                props: { to: menu.menuUrl },
                attrs: { style: 'overflow:hidden;white-space:normal;text-overflow:clip;' },
            };
            // 菜单
            if (menu.menuType === 'MENU') {
                return h(Item, { key: menu.menuId }, [
                    h(tag, config, [this.renderIcon(h, menu.menuIcon, menu.menuId), menu.menuName]),
                ]);
            }

            return h(Item, { key: menu.menuId }, [
                h(
                    'a',
                    {
                        attrs: { style: 'overflow:hidden;white-space:normal;text-overflow:clip;' },
                        on: {
                            click(e) {
                                e.preventDefault();
                            },
                        },
                    },
                    [this.renderIcon(h, menu.menuIcon, menu.menuId), menu.menuName],
                ),
            ]);
        },

        renderSubMenu(h, menu) {
            const subItem = [
                h(
                    'span',
                    {
                        slot: 'title',
                        attrs: { style: 'overflow:hidden;white-space:normal;text-overflow:clip;' },
                    },
                    [this.renderIcon(h, menu.menuIcon, menu.menuId), menu.menuName],
                ),
            ];
            const itemArr = [];

            menu.children.forEach(item => {
                itemArr.push(this.renderItem(h, item));
            });

            return h(SubMenu, { key: menu.menuId }, subItem.concat(itemArr));
        },

        renderItem(h, menu) {
            return menu.children && menu.children.length
                ? this.renderSubMenu(h, menu)
                : this.renderMenuItem(h, menu);
        },

        renderMenu(h, menuTree) {
            const menuArr = [];

            menuTree.forEach(menu => {
                menuArr.push(this.renderItem(h, menu));
            });

            return menuArr;
        },

        updateMenu() {
            this.selectedKeys = this.getSelectedKey();
            // 混合模式 不管
            if (this.mode !== 'horizontal') this.sOpenKeys = this.getOpenKeysByPath(this.$route.path);
        },

        getSelectedKey() {
            const { path } = this.$route;
            let routeToMenu = this.menuData.find(m => m.menuUrl === path);
            let parentMenuId = routeToMenu.parentMenuId;

            // 说明这是头部菜单
            if (this.mode === 'horizontal') {
                while (parentMenuId !== 0) {
                    routeToMenu = this.allMenuList.find(m => m.menuId === parentMenuId);
                    parentMenuId = routeToMenu.parentMenuId;
                }
                return [routeToMenu.menuId];
            }

            return [routeToMenu.menuId];
        },

        getOpenKeysByPath(path) {
            const { parentMenuId } = this.menuData.find(m => m.menuUrl === path);
            if (parentMenuId === 0) return [];
            const parentMenus = [parentMenuId];
            const res = [parentMenuId];
            while (parentMenus.length) {
                const menuId = parentMenus.pop();
                const parentMenu = this.allMenuList.find(m => m.menuId === menuId);
                if (parentMenu.parentMenuId !== 0) {
                    parentMenus.push(parentMenu.parentMenuId);
                    res.push(parentMenu.parentMenuId);
                }
            }
            return res;
        },
    },
    render(h) {
        return h(
            Menu,
            {
                props: {
                    theme: this.menuTheme,
                    mode: this.$props.mode,
                    selectedKeys: this.selectedKeys,
                    openKeys: this.sOpenKeys,
                },
                on: {
                    'update:openKeys': val => {
                        this.sOpenKeys = val;
                    },
                    click: obj => {
                        this.selectedKeys = [obj.key];
                        this.$emit('select', obj);
                    },
                },
            },
            this.renderMenu(h, this.options),
        );
    },
};
