import React, { lazy, useState, useEffect, useMemo, useCallback, Suspense } from 'react';
import { makeStyles, Drawer, useMediaQuery, useTheme } from '@material-ui/core';
import NavigationSidebar from './ui/NavigationSidebar';
import SiteHeader from './ui/SiteHeader';
import { UtilityBar } from '../UI/utilityDisplay/UtilityBar';
import { useTranslation } from 'react-i18next';
import { getMenuItemsRecursively, findHomeRouteSlug } from '../utilities/menus/menuUtilities';
import clsx from 'clsx';
import PropTypes from 'prop-types';
import { useUser } from '../utilities/auth/useUser';
import { ActionProvider } from '../utilities/provider/ActionProvider';
import { PageActionWrapper } from '../actions/PageActionWrapper';
import { useInquiryStore } from '../stores/inquiryStore';
import { useWidgetRegistry } from './useWidgetRegistry';
import { useBuildEnvironment, APP_RIBBON_SPACE } from './ui/useBuildEnvironment';
import { ChatBotProvider } from '../utilities/chatBot/ChatBotProvider';
import { UserProfileMenuWrapper } from '../shell/ui/profile';
import { useMenuContext } from '../utilities/menus/MenuProvider';
//import { usePreloadPages } from '../hooks/usePreloadPages';
import { Switch } from 'react-router-dom';
import { UdpRoutes } from '../routes/UdpRoutes';
import { useRouteRegistry } from '../routes/routeRegistryStore';
import { useShellVisibility } from './useShellVisibility';
import { PageLoading } from '../UI';
import ErrorBoundary from '../errorBoundary/ErrorBoundary';
// Lazy-load components that only render in response to user interaction or
// optional props, so they don't get pulled into the Shell entry chunk.
const FUIAppSwitcher = lazy(() => import('./ui/appSwitcher/FUIAppSwitcher'));
const UtilitySideBar = lazy(() => import('../UI/utilityDisplay/UtilitySideBar').then((m) => ({
    default: m.UtilitySideBar,
})));
const MenuTypeEnums = {
    Left_Menu: 1,
    Application_Menu: 2,
    Builders_Menu: 3,
    Favorites_Menu: 4,
};
const useStyles = makeStyles((theme) => ({
    '@global': {
        html: {
            minHeight: '100%',
        },
        'html, body, #root': {
            display: 'flex',
            flexDirection: 'column',
        },
        'body, #root': {
            flex: 1,
        },
    },
    root: {
        flex: 1,
        minHeight: '100vh',
        display: 'grid',
        gridTemplateAreas: ['sidebar header', 'sidebar content'].map((line) => `"${line}"`).join(' '),
        gridTemplateColumns: 'auto 1fr',
        gridTemplateRows: 'auto 1fr',
    },
    header: {
        gridArea: 'header',
    },
    sidebar: {
        gridArea: 'sidebar',
    },
    content: {
        gridArea: 'content',
        display: 'flex',
        flexDirection: 'column',
        position: 'relative',
        zIndex: 1,
        height: ({ appRibbonSpace }) => `calc(100vh - ${56 + appRibbonSpace}px)`,
        overflowY: 'auto',
    },
    paper: {
        width: '100%',
        [theme.breakpoints.up('sm')]: {
            width: (props) => props.drawerWidth || 520,
        },
    },
}), { name: 'Layout' });
/**
 * Core site layout common to all pages
 */
export const Shell = (props) => {
    const buildEnv = useBuildEnvironment();
    const classes = useStyles(Object.assign(Object.assign({}, props), { ribbonSpace: buildEnv ? APP_RIBBON_SPACE : 0 }));
    const { children, userAvatar = React.createElement(UserProfileMenuWrapper, null), appContent, leftMenu, appSelectorMenus, siteName, className, navRoot, hideToggle, useMockData, mockMenus, user: passedInUser, unityUrl, expander, sidebarTitle, navMenuHoverOn = false, secondExtended, toggleOne, toggleTwo, closePrimary, closeSecondary, panelExpanded, panelExpandedSecondary, setPanelExpanded = false, setPanelExpandedSecondary = false, breadCrumbAltLabelList = [], currentLocation, utilitySidebarResizable, utilitySidebarToggleOverride, onUtilitySidebarToggleExpandClick, hideLayout = false, getAccessToken, switcherData, selectedItem, switcherWidth, languages, projectSwitcherColor, widgets, 
    /** @deprecated Use `widgets` prop instead */
    getWidget: getWidgetProp, 
    /** @deprecated Use `widgets` prop instead */
    isValidWidget: isValidWidgetProp, appSwitcherHeader, hamburgerMenuAccessRole, hideLanguageSwitcher = false, subheader, hideHelpCenter = false, leftMenuLoading = false, } = props;
    const contextUser = useUser();
    const user = passedInUser !== null && passedInUser !== void 0 ? passedInUser : contextUser;
    useWidgetRegistry({ widgets, getWidget: getWidgetProp, isValidWidget: isValidWidgetProp });
    const routeConfig = useRouteRegistry((state) => state.routeMap[state.currentPath]);
    const isPublicRoute = (routeConfig === null || routeConfig === void 0 ? void 0 : routeConfig.isPublic) !== false;
    const [appSwitcherMobile, setAppSwitcherMobile] = useState(false);
    const [appSwitcherDesktop, setAppSwitcherDesktop] = useState(false);
    const { i18n } = useTranslation();
    const inquiryTitle = useInquiryStore((state) => state.title);
    //usePreloadPages();
    const menuContext = useMenuContext === null || useMenuContext === void 0 ? void 0 : useMenuContext();
    const resolvedLeftMenu = useMemo(() => (leftMenuLoading ? [] : (leftMenu !== null && leftMenu !== void 0 ? leftMenu : menuContext === null || menuContext === void 0 ? void 0 : menuContext.leftMenu)), [leftMenuLoading, leftMenu, menuContext]);
    const homeRoute = useMemo(() => ((leftMenu === null || leftMenu === void 0 ? void 0 : leftMenu.length) ? findHomeRouteSlug(leftMenu) : menuContext === null || menuContext === void 0 ? void 0 : menuContext.homeRoute), [leftMenu, menuContext]);
    const resolvedAppSelectorMenus = appSelectorMenus !== null && appSelectorMenus !== void 0 ? appSelectorMenus : menuContext === null || menuContext === void 0 ? void 0 : menuContext.appSelectorMenus;
    const providedLanguages = languages !== null && languages !== void 0 ? languages : menuContext === null || menuContext === void 0 ? void 0 : menuContext.languages;
    const resolvedLanguages = Array.isArray(providedLanguages) ? providedLanguages : [];
    const effectiveShellHidden = useShellVisibility({
        hideLayout,
        isPublicRoute,
        hasUser: Boolean(user === null || user === void 0 ? void 0 : user.id),
    });
    const getMenuItems = useCallback((menuTypeId, menus) => {
        if (!menus && !useMockData) {
            return [];
        }
        const menusToFilter = useMockData ? mockMenus : menus;
        const foundMenus = menusToFilter.filter((menu) => menu.menuTypeId === menuTypeId && menu.active);
        if (foundMenus) {
            return foundMenus.reduce((menuItemInstanceStructureViews, menu) => {
                return [...menuItemInstanceStructureViews, ...menu.menuItemInstanceStructureViews];
            }, []);
        }
        else {
            return [];
        }
    }, [useMockData, mockMenus]);
    const menus = useMemo(() => {
        const menuItems = getMenuItems(1, resolvedLeftMenu);
        return getMenuItemsRecursively(menuItems, true, user);
    }, [getMenuItems, user, resolvedLeftMenu]);
    const theme = useTheme();
    const mobile = useMediaQuery(theme.breakpoints.up('sm'));
    const handleAppSwitcher = (type, bool) => {
        if (type === 'mobile') {
            setAppSwitcherMobile(bool);
        }
        else {
            setAppSwitcherDesktop(bool);
        }
    };
    const builderMenu = useMemo(() => {
        const menuItems = getMenuItems(MenuTypeEnums.Builders_Menu, resolvedAppSelectorMenus);
        return getMenuItemsRecursively(menuItems, true, user, getAccessToken);
    }, [getMenuItems, user, resolvedAppSelectorMenus, getAccessToken]);
    const favoriteMenu = useMemo(() => {
        const menuItems = getMenuItems(MenuTypeEnums.Favorites_Menu, resolvedAppSelectorMenus);
        return getMenuItemsRecursively(menuItems, true, user, getAccessToken);
    }, [getMenuItems, user, resolvedAppSelectorMenus, getAccessToken]);
    const appMenu = useMemo(() => {
        const menuItems = getMenuItems(MenuTypeEnums.Application_Menu, resolvedAppSelectorMenus);
        return getMenuItemsRecursively(menuItems, true, user, getAccessToken);
    }, [getMenuItems, user, resolvedAppSelectorMenus, getAccessToken]);
    const hideAppMenu = useMemo(() => !resolvedAppSelectorMenus ||
        (hamburgerMenuAccessRole && !(user === null || user === void 0 ? void 0 : user.roleNames.includes(hamburgerMenuAccessRole))), [user, resolvedAppSelectorMenus, hamburgerMenuAccessRole]);
    useEffect(() => {
        i18n.changeLanguage('en-US');
    }, [i18n]);
    return (React.createElement(ChatBotProvider, null, React.createElement(ActionProvider, null, React.createElement("div", { className: classes.root }, !effectiveShellHidden && (React.createElement(SiteHeader, { className: classes.header, siteName: siteName, appContent: appContent, userAvatar: userAvatar, breadCrumbRoot: navRoot, setAppSwitcherOpen: (type, bool) => handleAppSwitcher(type, bool), breadCrumbAltLabelList: breadCrumbAltLabelList, currentLocation: currentLocation, switcherData: switcherData, selectedItem: selectedItem, switcherWidth: switcherWidth, hideAppLaunch: hideAppMenu, languages: resolvedLanguages, hideLanguageSwitcher: hideLanguageSwitcher, backgroundColor: projectSwitcherColor, hideHelpCenter: hideHelpCenter })), React.createElement("div", { style: { display: 'flex' }, className: classes.sidebar }, !effectiveShellHidden && mobile && (React.createElement(NavigationSidebar, { className: classes.sidebar, data: menus, navMenuHoverOn: navMenuHoverOn, user: user, useGlobalState: true, leftMenuLoading: leftMenuLoading || (menuContext === null || menuContext === void 0 ? void 0 : menuContext.leftMenuLoading) })), expander && (React.createElement("div", null, React.createElement(Suspense, { fallback: null }, React.createElement(UtilitySideBar, Object.assign({ title: inquiryTitle || sidebarTitle, resizable: utilitySidebarResizable, utilitySidebarToggleOverride: utilitySidebarToggleOverride, onUtilitySidebarToggleExpandClick: onUtilitySidebarToggleExpandClick, sidebarHidden: effectiveShellHidden }, props)))))), React.createElement("div", { className: classes.content }, !effectiveShellHidden && subheader, React.createElement(UtilityBar, { className: clsx(className), gutters: false, hideToggle: hideToggle, expander: expander, secondExtended: secondExtended, toggleOne: toggleOne, toggleTwo: toggleTwo, closePrimary: closePrimary, closeSecondary: closeSecondary, expanded: panelExpanded, expandedSecondary: panelExpandedSecondary, setExpanded: setPanelExpanded, setExpandedSecondary: setPanelExpandedSecondary }), React.createElement(ErrorBoundary, null, React.createElement(PageActionWrapper, null, React.createElement(Suspense, { fallback: React.createElement(PageLoading, null) }, React.createElement(Switch, null, children, React.createElement(UdpRoutes, { homeRoute: homeRoute })))))), React.createElement(Drawer, { variant: "temporary", anchor: "left", open: appSwitcherDesktop, classes: !mobile ? {} : !resolvedAppSelectorMenus ? {} : { paper: classes.paper }, onClose: () => handleAppSwitcher('desktop', false) }, mobile && resolvedAppSelectorMenus && (React.createElement(Suspense, { fallback: null }, React.createElement(FUIAppSwitcher, { onClose: () => handleAppSwitcher('desktop', false), favoriteMenu: favoriteMenu, builderMenu: builderMenu, appMenu: appMenu, unityUrl: unityUrl, user: user, header: appSwitcherHeader && typeof appSwitcherHeader === 'function'
            ? appSwitcherHeader(() => {
                handleAppSwitcher('desktop', false);
            })
            : appSwitcherHeader }))), (!mobile || (mobile && !resolvedAppSelectorMenus)) && (React.createElement(NavigationSidebar, { toggle: false, className: classes.sidebar, data: menus, navMenuHoverOn: navMenuHoverOn, user: user, useGlobalState: true, leftMenuLoading: leftMenuLoading || (menuContext === null || menuContext === void 0 ? void 0 : menuContext.leftMenuLoading) }))), React.createElement(Drawer, { variant: "temporary", anchor: "right", open: appSwitcherMobile, classes: { paper: classes.paper }, onClose: () => handleAppSwitcher('mobile', false) }, React.createElement(Suspense, { fallback: null }, React.createElement(FUIAppSwitcher, { onClose: () => handleAppSwitcher('mobile', false), favoriteMenu: favoriteMenu, builderMenu: builderMenu, appMenu: appMenu, unityUrl: unityUrl, user: user, header: appSwitcherHeader && typeof appSwitcherHeader === 'function'
            ? appSwitcherHeader(() => {
                handleAppSwitcher('mobile', false);
            })
            : appSwitcherHeader })))))));
};
Shell.propTypes = {
    /**
     * The newest propTypes have been added but older ones are missing @todo: add missing propTypes for Shell.
     */
    /**
     * The array used to map for label and functions to list items.
     */
    switcherData: PropTypes.array,
    /**
     * The active label displayed.
     */
    selectedItem: PropTypes.string,
    /**
     *  Provides a method set the selector width. Default is 100.
     */
    switcherWidth: PropTypes.number,
    /**
     * Children nodes
     */
    children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired,
    /**
     * Name of site
     */
    siteName: PropTypes.string,
    /**
     * Component to render for the user Avatar
     */
    userAvatar: PropTypes.element,
    appContent: PropTypes.element,
    leftMenu: PropTypes.array,
    appSelectorMenus: PropTypes.array,
    className: PropTypes.object,
    navRoot: PropTypes.oneOfType([PropTypes.string, PropTypes.element, PropTypes.node]),
    /**
     * Should the shell use mock data
     */
    useMockData: PropTypes.bool,
    mockMenus: PropTypes.array,
    unityUrl: PropTypes.string,
    expander: PropTypes.bool,
    sidebarTitle: PropTypes.string,
    navMenuHoverOn: PropTypes.bool,
    toggleOne: PropTypes.bool,
    toggleTwo: PropTypes.bool,
    closePrimary: PropTypes.bool,
    closeSecondary: PropTypes.bool,
    panelExpanded: PropTypes.bool,
    panelExpandedSecondary: PropTypes.bool,
    setPanelExpanded: PropTypes.func,
    setPanelExpandedSecondary: PropTypes.func,
    breadCrumbAltLabelList: PropTypes.array,
    currentLocation: PropTypes.object,
    utilitySidebarResizable: PropTypes.bool,
    utilitySidebarToggleOverride: PropTypes.bool,
    onUtilitySidebarToggleExpandClick: PropTypes.func,
    hideLayout: PropTypes.bool,
    languages: PropTypes.arrayOf(PropTypes.object),
    /**
     * Passes the background color on the project switcher (default: theme secondary)
     */
    projectSwitcherColor: PropTypes.string,
    /**
     * Map of widget identifiers to React.lazy components.
     * Internally merged with UdpPagesLazy. Preferred over getWidget/isValidWidget.
     */
    widgets: PropTypes.object,
    /** @deprecated Use `widgets` prop instead */
    getWidget: PropTypes.func,
    /** @deprecated Use `widgets` prop instead */
    isValidWidget: PropTypes.func,
    currentTenant: PropTypes.object,
    hamburgerMenuAccessRole: PropTypes.string,
};
//# sourceMappingURL=Shell.js.map