import React, { useState, useEffect } from "react";
import classNames from "classnames";
import { StyledProps } from "../_type";
import { Icon } from "../icon";
import { MenuGroup } from "./MenuGroup";
import { SubMenu } from "./SubMenu";
import { MenuItem } from "./MenuItem";
import { useDefault } from "../_util/use-default";
import { Tooltip } from "../tooltip";
import { useConfig } from "../_util/config-context";
import { Badge } from "../badge";
import { MenuContext } from "./MenuContext";
import { forwardRefWithStatics } from "../_util/forward-ref-with-statics";

export interface MenuBackOptions {
  /**
   * 返回区域标题
   */
  title?: React.ReactNode;

  /**
   * 返回区域描述
   */
  description?: React.ReactNode;

  /**
   * 为该区域文字添加 Tooltip 说明
   */
  tooltip?: React.ReactNode;

  /**
   * 返回按钮点击回调
   */
  onClick?: (event: React.MouseEvent) => void;
}

export interface MenuProps extends StyledProps {
  /**
   * 标题
   */
  title?: React.ReactNode;

  /**
   * 标题旁标签内容
   */
  tag?: React.ReactNode;

  /**
   * 导航折叠后标题处显示的图标 URL 或自定义节点内容
   *
   * **传入 `string` 类型将作为 URL 解析**
   *
   * @docType [React.ReactNode, React.ReactNode] | React.ReactNode
   */
  icon?: React.ReactNode | [React.ReactNode, React.ReactNode];

  /**
   * 顶部返回区域相关配置
   */
  back?: MenuBackOptions;

  /**
   * 主题样式
   *
   * @default "light"
   */
  theme?: "light" | "dark";

  /**
   * 导航内容（Menu.Group 或 Menu.SubMenu 或 Menu.Item）
   */
  children?: React.ReactNode;

  /**
   * 导航是否支持折叠（展示底部折叠/展示操作区）
   *
   * 如开启支持请为菜单项配置图标
   *
   * @default false
   */
  collapsable?: boolean;

  /**
   * 导航是否默认被折叠
   *
   * @default false
   */
  defaultCollapsed?: boolean;

  /**
   * 导航是否被折叠
   *
   * @default false
   */
  collapsed?: boolean;

  /**
   * 导航折叠变化时回调
   */
  onCollapsedChange?: (collapsed: boolean) => void;
}

export const Menu = forwardRefWithStatics(
  function Menu(
    {
      theme,
      title,
      tag,
      icon,
      back,
      children,
      className,
      collapsable,
      defaultCollapsed = false,
      collapsed,
      onCollapsedChange,
      ...props
    }: MenuProps,
    ref: React.Ref<HTMLDivElement>
  ) {
    const { classPrefix } = useConfig();

    // eslint-disable-next-line no-param-reassign
    [collapsed, onCollapsedChange] = useDefault(
      collapsed,
      defaultCollapsed,
      onCollapsedChange
    );

    const [hover, setHover] = useState<boolean>(false);
    const [mobileCollapsed, setMobileCollapsed] = useState<boolean>(false);

    useEffect(() => {
      if (!collapsed) {
        setHover(false);
      }
    }, [collapsed]);

    if (Array.isArray(icon)) {
      // eslint-disable-next-line
      icon = icon[0];
    }

    const renderBack =
      typeof back === "object"
        ? () => {
            const { title, description, onClick = () => null, tooltip } = back;
            const titleList = (
              <div className={`${classPrefix}-menu__title-list`}>
                <div
                  className={classNames(`${classPrefix}-h2`, {
                    [`${classPrefix}-menu__title-main`]: !!description,
                  })}
                >
                  {title}
                </div>
                <div className={`${classPrefix}-menu__title-text`}>
                  {description}
                </div>
              </div>
            );
            return (
              <div className={`${classPrefix}-menu__title-back`}>
                <a className={`${classPrefix}-menu__back`} onClick={onClick}>
                  <Icon type="btnback" />
                </a>
                {tooltip ? (
                  <Tooltip title={tooltip}>{titleList}</Tooltip>
                ) : (
                  titleList
                )}
              </div>
            );
          }
        : () => null;

    return (
      <MenuContext.Provider
        value={{ collapsed: collapsed && !hover, setMobileCollapsed }}
      >
        <div
          ref={ref}
          className={classNames(`${classPrefix}-menu`, className, {
            [`${classPrefix}-menu--light`]: theme !== "dark",
            [`${classPrefix}-menu-is-locked`]: collapsed,
            [`${classPrefix}-menu-is-collapsed`]: collapsed && !hover,
            [`${classPrefix}-menu-mobile-collapsed`]: mobileCollapsed,
          })}
          {...props}
        >
          <div
            className={`${classPrefix}-menu__header`}
            onMouseEnter={() => collapsed && setHover(true)}
            onMouseLeave={() => collapsed && setHover(false)}
            onClick={() => setMobileCollapsed(collapsed => !collapsed)}
          >
            {!!title && (
              <div className={`${classPrefix}-menu__title`}>
                {!!icon &&
                  (typeof icon === "string" ? (
                    <img
                      className={`${classPrefix}-menu__title-icon`}
                      src={icon}
                      alt="icon"
                    />
                  ) : (
                    icon
                  ))}
                <h2 className={`${classPrefix}-h2`}>
                  {title}
                  {!!tag && <Badge>{tag}</Badge>}
                </h2>
                <Icon type="arrowdown" />
              </div>
            )}
            {renderBack()}
          </div>
          <div
            className={`${classPrefix}-menu__body`}
            onMouseEnter={() => collapsed && setHover(true)}
            onMouseLeave={() => collapsed && setHover(false)}
          >
            <ul className={`${classPrefix}-menu__list`}>{children}</ul>
          </div>
          {!!collapsable && (
            <div className={`${classPrefix}-menu__footer`}>
              <div
                className={`${classPrefix}-menu__fold`}
                onClick={() => onCollapsedChange(!collapsed)}
              >
                <div className={`${classPrefix}-menu__fold-icon`}>
                  <Icon type="fold" />
                </div>
              </div>
            </div>
          )}
        </div>
      </MenuContext.Provider>
    );
  },
  {
    Group: MenuGroup,
    SubMenu,
    Item: MenuItem,
  }
);

Menu.displayName = "Menu";

export { MenuGroupProps } from "./MenuGroup";
export { MenuItemProps } from "./MenuItem";
export { SubMenuProps } from "./SubMenu";
