import "core-js/modules/es.array.iterator.js";
import "core-js/modules/web.dom-collections.iterator.js";
import "core-js/modules/es.promise.js";
import "core-js/modules/es.regexp.exec.js";
import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react';
import classNames from 'classnames';
import warning from 'warning';
import useMergedState from 'rc-util/es/hooks/useMergedState';
import Omit from 'omit.js';
import { getMatchMenu } from '@umijs/route-utils';
import useSWR, { mutate } from 'swr';
import ConfigProvider from '../config-provider';
import Layout from '../layout';
import { safeJSONStringify as stringify, useDeepCompareEffect, useDocumentTitle, isBrowser, useMountMergeState } from '../utils';
import useAntdMediaQuery from 'use-media-antd-query';
import Header from './Header';
import { getPageTitleInfo } from './getPageTitle';
import defaultSettings from './defaultSettings';
import getLocales from './locales';
import Footer from './Footer';
import RouteContext from '../wau-route-context';
import SiderMenu from './components/SiderMenu';
import { getBreadcrumbProps } from './utils/getBreadcrumbProps';
import getMenuData from './utils/getMenuData';
import PageLoading from '../wau-page-loading';
import MenuCounter from './components/SiderMenu/Counter';
import WrapContent from './WrapContent';
import compatibleLayout from './utils/compatibleLayout';
import useCurrentMenuLayoutProps from './utils/useCurrentMenuLayoutProps';
import { clearMenuItem } from './utils/utils';
import { jsx as _jsx } from "react/jsx-runtime";
import { jsxs as _jsxs } from "react/jsx-runtime";
let layoutIndex = 0;
const headerRender = (props, matchMenuKeys) => {
  if (props.headerRender === false || props.pure) {
    return null;
  }
  return /*#__PURE__*/_jsx(Header, {
    matchMenuKeys: matchMenuKeys,
    ...props
  });
};
const footerRender = props => {
  if (props.footerRender === false || props.pure) {
    return null;
  }
  if (props.footerRender) {
    return props.footerRender({
      ...props
    }, /*#__PURE__*/_jsx(Footer, {}));
  }
  return null;
};
const renderSiderMenu = (props, matchMenuKeys) => {
  const {
    layout,
    isMobile,
    openKeys,
    splitMenus,
    menuRender
  } = props;
  if (props.menuRender === false || props.pure) {
    return null;
  }
  let {
    menuData
  } = props;

  /** 如果是分割菜单模式，需要专门实现一下 */
  if (splitMenus && (openKeys !== false || layout === 'mix') && !isMobile) {
    const [key] = matchMenuKeys;
    if (key) {
      var _props$menuData;
      menuData = ((_props$menuData = props.menuData) === null || _props$menuData === void 0 || (_props$menuData = _props$menuData.find(item => item.key === key)) === null || _props$menuData === void 0 ? void 0 : _props$menuData.children) || [];
    } else {
      menuData = [];
    }
  }
  // 这里走了可以少一次循环
  const clearMenuData = clearMenuItem(menuData || []);
  if (clearMenuData && (clearMenuData === null || clearMenuData === void 0 ? void 0 : clearMenuData.length) < 1 && splitMenus) {
    return null;
  }
  if (layout === 'top' && !isMobile) {
    return /*#__PURE__*/_jsx(SiderMenu, {
      matchMenuKeys: matchMenuKeys,
      ...props,
      hide: true
    });
  }
  if (menuRender) {
    const defaultDom = /*#__PURE__*/_jsx(SiderMenu, {
      matchMenuKeys: matchMenuKeys,
      ...props,
      // 这里走了可以少一次循环
      menuData: clearMenuData
    });
    return menuRender(props, defaultDom);
  }
  return /*#__PURE__*/_jsx(SiderMenu, {
    matchMenuKeys: matchMenuKeys,
    ...props,
    // 这里走了可以少一次循环
    menuData: clearMenuData
  });
};
const defaultPageTitleRender = (pageProps, props) => {
  const {
    pageTitleRender
  } = props;
  const pageTitleInfo = getPageTitleInfo(pageProps);
  if (pageTitleRender === false) {
    return {
      title: props.title || '',
      id: '',
      pageName: ''
    };
  }
  if (pageTitleRender) {
    const title = pageTitleRender(pageProps, pageTitleInfo.title, pageTitleInfo);
    if (typeof title === 'string') {
      return {
        ...pageTitleInfo,
        title
      };
    }
    warning(typeof title === 'string', 'pro-layout: renderPageTitle return value should be a string');
  }
  return pageTitleInfo;
};
const getPaddingLeft = (hasLeftPadding, collapsed, siderWidth, collapsedWidth) => {
  if (hasLeftPadding) {
    return collapsed ? collapsedWidth : siderWidth;
  }
  return 0;
};

/**
 * 🌃 Powerful and easy to use beautiful layout 🏄‍ Support multiple topics and layout types
 *
 * @param props
 */
const BasicLayout = props => {
  var _props$prefixCls, _location$pathname;
  const {
    children,
    onCollapse: propsOnCollapse,
    location = {
      pathname: '/'
    },
    contentStyle,
    route,
    defaultCollapsed,
    style,
    disableContentMargin,
    siderWidth = 232,
    collapsedWidth = 64,
    menu,
    isChildrenLayout: propsIsChildrenLayout,
    menuDataRender,
    actionRef,
    formatMessage: propsFormatMessage,
    loading
  } = props || {};
  const context = useContext(ConfigProvider.ConfigContext);
  const prefixCls = (_props$prefixCls = props.prefixCls) !== null && _props$prefixCls !== void 0 ? _props$prefixCls : context.getPrefixCls('pro');
  const [menuLoading, setMenuLoading] = useMountMergeState(false, {
    value: menu === null || menu === void 0 ? void 0 : menu.loading,
    onChange: menu === null || menu === void 0 ? void 0 : menu.onLoadingChange
  });

  // give a default key for swr
  const [defaultId] = useState(() => {
    layoutIndex += 1;
    return `pro-layout-${layoutIndex}`;
  });
  const formatMessage = useCallback(({
    id,
    defaultMessage,
    ...restParams
  }) => {
    if (propsFormatMessage) {
      return propsFormatMessage({
        id,
        defaultMessage,
        ...restParams
      });
    }
    const locales = getLocales();
    return locales[id] ? locales[id] : defaultMessage;
  }, [propsFormatMessage]);
  const [menuInfoData, setMenuInfoData] = useMergedState(() => getMenuData((route === null || route === void 0 ? void 0 : route.routes) || [], menu, formatMessage, menuDataRender));
  const {
    breadcrumb = {},
    breadcrumbMap,
    menuData = []
  } = menuInfoData || {};
  const {
    data
  } = useSWR(defaultId, async () => {
    var _menu$request;
    setMenuLoading(true);
    const msg = await (menu === null || menu === void 0 || (_menu$request = menu.request) === null || _menu$request === void 0 ? void 0 : _menu$request.call(menu, (menu === null || menu === void 0 ? void 0 : menu.params) || {}, (route === null || route === void 0 ? void 0 : route.routes) || []));
    setMenuLoading(false);
    return msg;
  }, {
    revalidateOnFocus: false,
    shouldRetryOnError: false,
    revalidateOnReconnect: false
  });

  // params 更新的时候重新请求
  useEffect(() => {
    if (!data) {
      return;
    }
    mutate(defaultId);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [defaultId, stringify(menu === null || menu === void 0 ? void 0 : menu.params)]);
  if (actionRef && menu !== null && menu !== void 0 && menu.request) {
    actionRef.current = {
      reload: () => {
        mutate(defaultId);
      }
    };
  }
  useDeepCompareEffect(() => {
    if (!(menu !== null && menu !== void 0 && menu.request) || !(data !== null && data !== void 0 && data.length)) {
      return;
    }
    const menuDataMap = getMenuData(data || (route === null || route === void 0 ? void 0 : route.routes) || [], menu, formatMessage, menuDataRender);
    setMenuInfoData(menuDataMap);
  }, [data, menu === null || menu === void 0 ? void 0 : menu.request, menu === null || menu === void 0 ? void 0 : menu.loading, route === null || route === void 0 ? void 0 : route.routes]);
  const matchMenus = useMemo(() => {
    return getMatchMenu(location.pathname || '/', menuData || [], true);
  }, [location.pathname, menuData]);
  const matchMenuKeys = useMemo(() => Array.from(new Set(matchMenus.map(item => item.key || item.path || ''))), [matchMenus]);

  // 当前选中的menu，一般不会为空
  const currentMenu = matchMenus[matchMenus.length - 1] || {};
  const currentMenuLayoutProps = useCurrentMenuLayoutProps(currentMenu);
  const {
    fixSiderbar,
    navTheme,
    layout: defaultPropsLayout,
    ...rest
  } = {
    ...props,
    ...currentMenuLayoutProps
  };
  const propsLayout = compatibleLayout(defaultPropsLayout);
  const colSize = useAntdMediaQuery();
  const isMobile = (colSize === 'sm' || colSize === 'xs') && !props.disableMobile;

  /** 如果 menuRender 不存在，可以做一下性能优化 只要 routers 没有更新就不需要重新计算 */
  useDeepCompareEffect(() => {
    if (menu !== null && menu !== void 0 && menu.loading || menu !== null && menu !== void 0 && menu.request) {
      return () => null;
    }
    const infoData = getMenuData((route === null || route === void 0 ? void 0 : route.routes) || [], menu, formatMessage, menuDataRender);
    // 稍微慢一点 render，不然会造成性能问题，看起来像是菜单的卡顿
    const animationFrameId = requestAnimationFrame(() => {
      setMenuInfoData(infoData);
    });
    return () => window.cancelAnimationFrame && window.cancelAnimationFrame(animationFrameId);
  }, [menu === null || menu === void 0 ? void 0 : menu.loading, menu === null || menu === void 0 ? void 0 : menu.request, route === null || route === void 0 ? void 0 : route.routes, location === null || location === void 0 ? void 0 : location.pathname, menuDataRender]);

  // If it is a fix menu, calculate padding
  // don't need padding in phone mode
  const hasLeftPadding = propsLayout !== 'top' && !isMobile;
  const [collapsed, onCollapse] = useMergedState(() => defaultCollapsed || false, {
    value: props.collapsed,
    onChange: propsOnCollapse
  });

  // Splicing parameters, adding menuData and formatMessage in props
  const defaultProps = Omit({
    prefixCls,
    ...props,
    siderWidth,
    ...currentMenuLayoutProps,
    formatMessage,
    breadcrumb,
    menu: {
      ...menu,
      loading: menuLoading
    },
    layout: propsLayout
  }, ['className', 'style', 'breadcrumbRender']);

  // gen page title
  const pageTitleInfo = defaultPageTitleRender({
    pathname: location.pathname,
    ...defaultProps,
    breadcrumbMap
  }, props);

  // gen breadcrumbProps, parameter for pageHeader
  const breadcrumbProps = getBreadcrumbProps({
    ...defaultProps,
    breadcrumbRender: props.breadcrumbRender,
    breadcrumbMap
  });

  // render sider dom
  const siderMenuDom = renderSiderMenu({
    ...defaultProps,
    menuData,
    onCollapse,
    isMobile,
    theme: (navTheme || 'dark').toLocaleLowerCase().includes('dark') ? 'dark' : 'light',
    collapsed
  }, matchMenuKeys);

  // render header dom
  const headerDom = headerRender({
    ...defaultProps,
    hasSiderMenu: !!siderMenuDom,
    menuData,
    isMobile,
    collapsed,
    onCollapse,
    theme: (navTheme || 'dark').toLocaleLowerCase().includes('dark') ? 'dark' : 'light'
  }, matchMenuKeys);

  // render footer dom
  const footerDom = footerRender({
    isMobile,
    collapsed,
    ...defaultProps
  });
  const {
    isChildrenLayout: contextIsChildrenLayout
  } = useContext(RouteContext);

  // 如果 props 中定义，以 props 为准
  const isChildrenLayout = propsIsChildrenLayout !== undefined ? propsIsChildrenLayout : contextIsChildrenLayout;
  const baseClassName = `${prefixCls}-basicLayout`;
  // gen className
  const className = classNames(props.className, 'ant-design-pro', baseClassName, {
    [`screen-${colSize}`]: colSize,
    [`${baseClassName}-top-menu`]: propsLayout === 'top',
    [`${baseClassName}-is-children`]: isChildrenLayout,
    [`${baseClassName}-fix-siderbar`]: fixSiderbar,
    [`${baseClassName}-${propsLayout}`]: propsLayout
  });

  /** 计算 slider 的宽度 */
  const leftSiderWidth = getPaddingLeft(!!hasLeftPadding, collapsed, siderWidth, collapsedWidth);

  // siderMenuDom 为空的时候，不需要 padding
  const genLayoutStyle = {
    position: 'relative'
  };

  // if is some layout children, don't need min height
  if (isChildrenLayout || contentStyle && contentStyle.minHeight) {
    genLayoutStyle.minHeight = 0;
  }
  const contentClassName = classNames(`${baseClassName}-content`, {
    [`${baseClassName}-has-header`]: headerDom,
    [`${baseClassName}-content-disable-margin`]: disableContentMargin
  });

  /** 页面切换的时候触发 */
  useEffect(() => {
    var _props$onPageChange;
    (_props$onPageChange = props.onPageChange) === null || _props$onPageChange === void 0 ? void 0 : _props$onPageChange.call(props, props.location);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [location.pathname, (_location$pathname = location.pathname) === null || _location$pathname === void 0 ? void 0 : _location$pathname.search]);
  const [hasFooterToolbar, setHasFooterToolbar] = useState(false);
  useDocumentTitle(pageTitleInfo, props.title || false);
  return /*#__PURE__*/_jsx(MenuCounter.Provider, {
    children: /*#__PURE__*/_jsx(RouteContext.Provider, {
      value: {
        ...defaultProps,
        breadcrumb: breadcrumbProps,
        menuData,
        isMobile,
        collapsed,
        isChildrenLayout: true,
        title: pageTitleInfo.pageName,
        hasSiderMenu: !!siderMenuDom,
        hasHeader: !!headerDom,
        siderWidth: leftSiderWidth,
        hasFooter: !!footerDom,
        hasFooterToolbar,
        setHasFooterToolbar,
        pageTitleInfo,
        matchMenus,
        matchMenuKeys,
        currentMenu
      },
      children: props.pure ? children : /*#__PURE__*/_jsx("div", {
        className: className,
        children: /*#__PURE__*/_jsxs(Layout, {
          style: {
            minHeight: '100%',
            ...style
          },
          children: [siderMenuDom, /*#__PURE__*/_jsxs("div", {
            style: genLayoutStyle,
            className: context.getPrefixCls('layout'),
            children: [headerDom, /*#__PURE__*/_jsx(WrapContent, {
              isChildrenLayout: isChildrenLayout,
              ...rest,
              className: contentClassName,
              style: contentStyle,
              children: loading ? /*#__PURE__*/_jsx(PageLoading, {}) : children
            }), footerDom]
          })]
        })
      })
    })
  });
};
BasicLayout.defaultProps = {
  logo: 'data:image/png;base64, ',
  ...defaultSettings,
  location: isBrowser() ? window.location : undefined
};
export default BasicLayout;