import { Layout, Menu, Icon } from 'antd';
import * as React from 'react';
const { SubMenu, Item: ItemMenu, ItemGroup } = Menu;
const { Sider } = Layout;
import { Iconfont } from '../Iconfont/Iconfont';
import { MenuMode } from 'antd/lib/menu';
import { SiderTheme } from 'antd/lib/layout/Sider';
import { PageComponent } from '../../types/index';
import { throttleWrap } from 'jad-tool'

import { isString, isFunction } from 'jad-tool'

type SiderProps = {
    width?: string | number;
    trigger?: string | React.ReactNode;
    collapsedWidth?: number;
    zeroWidthTriggerStyle?: object;
    [propName: string]: any;
}
type PropsKeyValue = {
    propPKeys: string,
    propKey: string,
    propName: string,
    propType: string,
}
type MenuDataProps = {
    key: string | number;
    name: string | number;
    pKeys?: (string | number)[];
    icon?: any;
    path?: string;
    children?: MenuDataProps[];
    type?: 'group' | 'menu'; // 默认是 'menu' —— 对应 SubMenu 和 ItemMenu
    keyValue?: PropsKeyValue,
    [propName: string]: any;
}
export class Sidebar extends React.Component<PageComponent<
    {
        title?: string | JSX.Element;
        data?: MenuDataProps[];
        logo?: any;
        ifCollapsed?: boolean,
        openKeys?: string[];
        selectedKeys?: string[];
        siderProps?: SiderProps;
        clickOpenWhoseAllChildren?: number; // 目的是为了模拟menu.group的交互效果，设计师希望点击1级菜单后它所有更深层次菜单默认展开
        onOpenMenuByKey?: (key: string[]) => any
        onClickMenuKey?: (key: string) => any
        onUpdateCollapsed?: (collapsed: boolean) => any
    }>> {
    keyValue = {
        propPKeys: 'pKeys',
        propKey: 'key',
        propName: 'name',
        propType: 'type',
    }
    constructor(props) {
        super(props);

        if (props['keyValue'])
            this.keyValue = {
                propPKeys: props['keyValue']['propPKeys'] || this.keyValue.propPKeys,
                propKey: props['keyValue']['propKey'] || this.keyValue.propKey,
                propName: props['keyValue']['propName'] || this.keyValue.propName,
                propType: props['keyValue']['propType'] || this.keyValue.propType,
            }
    }
    public dispatchResize = throttleWrap(300)(() => {
        //ie兼容
        if (navigator.userAgent.indexOf('MSIE') !== -1 || navigator.appVersion.indexOf('Trident/') > 0) {
            var evt = document.createEvent('UIEvents') as any;
            evt.initUIEvent('resize', true, false, window, 0);
            window.dispatchEvent(evt);
        } else {
            window.dispatchEvent(new Event('resize'));
        }
    })
    onOpenChange(e) {
        const { onOpenMenuByKey = (key) => null, clickOpenWhoseAllChildren } = this.props;
        const { propPKeys, propKey } = this.keyValue;
        let keys = [];
        /* e.pKeys: string[]；如1级菜单的pKeys.length为0，2级菜单的pKeys.length为1 (propPKeys 默认取值 pKeys) */
        if (clickOpenWhoseAllChildren === (e[propPKeys].length + 1) && e.children) {
            /* 最底层可不查：children 不存在或[] */
            const findChildrenOpenKeys = (data) => data.map(f => {
                if (f.children && f.children.length) {
                    findChildrenOpenKeys(f.children);
                    /* 最底层可不查不存(因为是openKeys)：children 不存在或[] */
                    keys[keys.length] = f[propKey];
                }
            });
            findChildrenOpenKeys(e.children)
        }
        keys = [...e[propPKeys], ...keys, e[propKey]].filter(e => e);
        onOpenMenuByKey(keys)
    }
    onClickChange(key) {
        const { onClickMenuKey = (key) => null } = this.props
        onClickMenuKey(key)
    }
    onCollapse = (collapsed: boolean) => {
        const { onUpdateCollapsed = (collapsed) => null } = this.props
        onUpdateCollapsed(collapsed)
        this.dispatchResize()
    }
    recursionMenus = (menuItem: MenuDataProps) => {
        const { propKey, propName } = this.keyValue;
        if (!menuItem || !menuItem[propKey]) return
        const { propType } = this.keyValue;
        const menuType = menuItem[propType] || 'menu';
        let menuIcon = menuItem.icon;
        let menuTitle = <>
            {
                menuIcon ?
                    isFunction(menuIcon) ? menuIcon(menuItem) :
                        <Iconfont type={menuIcon} /> : null
            }
            <span>{menuItem[propName]}</span>
        </>
        if (menuItem.children && menuItem.children.length) {
            switch (menuType) {
                case 'group': // ItemGroup
                    return (
                        <ItemGroup key={menuItem[propKey]} title={menuTitle as any}>
                            {menuItem.children.map((d) => this.recursionMenus(d))}
                        </ItemGroup>
                    );
                case 'menu': // SubMenu
                default:
                    return (
                        <SubMenu key={menuItem[propKey]} title={menuTitle} onTitleClick={() => { this.onOpenChange(menuItem) }} >
                            {menuItem.children.map((d) => this.recursionMenus(d))}
                        </SubMenu>
                    )
            }
        } else return ( // ItemMenu
            <ItemMenu key={menuItem[propKey]} onClick={() => { this.onClickChange(menuItem[propKey]) }}>
                {
                    (menuItem.outer && menuItem.outer.url)
                        ? <a href={`${menuItem.outer.url}`} target={menuItem.outer.target || "_blank"}>{menuTitle}</a>
                        : <a href={`#${menuItem.path}`}>{menuTitle}</a>
                }
            </ItemMenu>
        )
    }
    renderMenus = (data: MenuDataProps[]) => {
        if (!data.length) return;
        return data.map((item) => this.recursionMenus(item))
    }
    public render() {
        const { ifCollapsed, title, data = [], selectedKeys, openKeys, logo, siderProps = { width: 208, collapsedWidth: 50 } } = this.props;
        const menuProps = {
            theme: 'dark' as SiderTheme,
            mode: 'inline' as MenuMode,
            // inlineIndent:30,
            selectedKeys,
            openKeys,
        }

        if (ifCollapsed) delete menuProps.openKeys;
        const menu = (
            <Menu
                {...menuProps}
            >
                {this.renderMenus(data)}
            </Menu>
        );

        return (
            <Sider
                collapsible
                width={siderProps.width}
                collapsed={ifCollapsed}
                onCollapse={this.onCollapse}
                collapsedWidth={siderProps.collapsedWidth}
            >
                <div style={{ height: '50px' }}>
                    <div className="jad-sidebar-header">
                        {
                            logo ? (
                                isString(logo) ? <i className="jad-sidebar-header-icon" style={{ backgroundSize: "100% 100%", display: 'inline-block', 'width': '30px', 'height': '30px', backgroundImage: 'url(' + logo + ')' }}></i> : logo
                            ) :
                                <Iconfont
                                    type="icon-logo"
                                    className="jad-sidebar-header-icon"
                                />
                        }

                        <p style={{ margin: "0 0 0 10px", fontSize: '16px', fontWeight: 500 }}>{ifCollapsed ? '' : title}</p>
                    </div>
                </div>
                {menu}
            </Sider>
        );
    }
}
