/**
 * 该插件可根据菜单配置自动生成 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';

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: [],
        };
    },
    computed: {
        menuTheme() {
            return this.theme == 'light' ? this.theme : 'dark';
        },
    },
    created() {
        const { menuList } = getUserInfo();
        this.menuData = menuList.filter(i => i.menuType === 'MENU');
        this.updateMenu();
        // // 自定义国际化配置
        // if (this.i18n && this.i18n.messages) {
        //     const messages = this.i18n.messages;
        //     Object.keys(messages).forEach(key => {
        //         this.$i18n.mergeLocaleMessage(key, messages[key]);
        //     });
        // }
    },
    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;
            }
        },
        $route: function() {
            this.updateMenu();
        },
        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.path },
                attrs: { style: 'overflow:hidden;white-space:normal;text-overflow:clip;' },
            };

            return h(Item, { key: menu.menuId }, [
                h(tag, config, [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) {
            let menuArr = [];
            menuTree.forEach((menu, i) => {
                menuArr.push(this.renderItem(h, menu));
            });
            return menuArr;
        },

        updateMenu() {
            this.selectedKeys = this.getSelectedKey(this.$route);

            // let openKeys = matchedRoutes.map(item => item.path);

            // openKeys = openKeys.slice(0, openKeys.length - 1);

            // if (!fastEqual(openKeys, this.sOpenKeys)) {
            //     this.collapsed || this.mode === 'horizontal'
            //         ? (this.cachedOpenKeys = openKeys)
            //         : (this.sOpenKeys = openKeys);
            // }
            this.sOpenKeys = this.getOpenKeysByPath(this.$route.path);
        },
        getSelectedKey(route) {
            const { path } = route;
            return [this.menuData.find(m => m.menuUrl === path).menuId];
        },

        getOpenKeysByPath(path) {
            const { menuList } = getUserInfo();
            const { parentMenuId } = this.menuData.find(m => m.menuUrl === path);
            const parentMenus = [parentMenuId];
            const res = [parentMenuId];
            while (parentMenus.length) {
                const menuId = parentMenus.pop();
                const parentMenu = menuList.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 => {
                        obj.selectedKeys = [obj.key];
                        this.$emit('select', obj);
                    },
                },
            },
            this.renderMenu(h, this.options),
        );
    },
};
