import { useResizeObserver } from '@planview/pv-utilities'
import * as React from 'react'
import { RovingTabIndexProvider } from '../react-roving-tabindex'
import { defineMessages, useIntl } from 'react-intl'
import { ToolbarSeparator } from '..'
import { getBreakPoint, shouldDisplayAtBreakpoint } from '../utils'
import type { ResizeContextType, UserMenuConfig } from '../utils/context'
import ResizeContext, {
    MainNavigationContext,
    UserMenuContext,
} from '../utils/context'
import {
    LeftWrap,
    NavigationBarStaticWrap,
    RightWrap,
    StyledNavigationBar,
} from './styles'
import { UserMenuInternal as UserMenu } from './user-menu'
import { useMergeRefs } from '../utils/refs'

const messages = defineMessages({
    userMenu: {
        id: 'pvds.toolbar.navigation.userMenu',
        defaultMessage: 'User menu',
        description: 'Label for user menu (tooltip and label in dropdown)',
    },
})

export type NavigationBarProps = {
    /**
     * Product logo: Can be one of the logos shipped in this library or custom element. If using custom logo make sure to hook logo up to navigation using `ToolbarItem`
     */
    logo?: React.JSX.Element
    /**
     * Customizable content of the navigation (between product logo and user menu).
     *
     * The content should be grouped in one `ToolbarSectionLeft` (wrapping content to the left) and one `ToolbarSectionRight` (wrapping content to the right)
     *
     */
    children: React.ReactNode

    /**
     * Element to inject ApplicationSwitcher to the correct place in the navigation bar
     */
    productSwitcher?: React.JSX.Element

    /**
     * If the left most separator should be displayed, defaults to true.
     *
     * it is [best practice](https://design.planview.com/components/navigation/navigation-bar#left-section) to remove the separator when there is nothing to display in the left content of the main navigation.
     */
    showLogoSeparator?: boolean
} & React.HTMLAttributes<HTMLElement>

const NavigationBarImpl: React.ForwardRefRenderFunction<
    HTMLElement | undefined,
    NavigationBarProps
> = (
    { logo, children, productSwitcher, showLogoSeparator = true, ...rest },
    ref
) => {
    const { formatMessage } = useIntl()
    const wrapperRef = React.useRef<HTMLElement>(undefined)
    const { width } = useResizeObserver({ ref: wrapperRef })
    const initialized = !!width
    const { breakpoint, showLabels, showSeparators } = getBreakPoint(width)
    const [userMenu, setUserMenu] = React.useState<UserMenuConfig | null>(null)

    const userMenuState = React.useMemo(
        () => ({
            add: (config: UserMenuConfig) => setUserMenu(config),
            remove: () => setUserMenu(null),
        }),
        []
    )

    const resizeContext = React.useMemo<ResizeContextType>(
        () => ({
            initialized,
            breakpoint,
            showLabels,
            showSeparators,
            shouldDisplay: (displayOn) =>
                shouldDisplayAtBreakpoint(breakpoint, displayOn),
        }),
        [breakpoint, showLabels, showSeparators, initialized]
    )

    const mergedRefs = useMergeRefs([ref, wrapperRef])

    return (
        <StyledNavigationBar {...rest} role="navigation" ref={mergedRefs}>
            <NavigationBarStaticWrap className="pvds-static">
                <MainNavigationContext.Provider
                    value={{ wrappedInNavigation: true }}
                >
                    <UserMenuContext.Provider value={userMenuState}>
                        <ResizeContext.Provider value={resizeContext}>
                            <RovingTabIndexProvider
                                options={{
                                    focusOnClick: false,
                                    loopAround: false,
                                }}
                            >
                                {!!logo || !!productSwitcher ? (
                                    <LeftWrap
                                        $compact={
                                            !showSeparators ||
                                            !showLogoSeparator
                                        }
                                    >
                                        {productSwitcher}
                                        {logo}
                                        {showLogoSeparator && (
                                            <ToolbarSeparator />
                                        )}
                                    </LeftWrap>
                                ) : null}
                                <RightWrap>{children}</RightWrap>
                                {userMenu ? (
                                    <UserMenu
                                        label={formatMessage(messages.userMenu)}
                                        trigger={userMenu.trigger}
                                    >
                                        {userMenu.children}
                                    </UserMenu>
                                ) : null}
                            </RovingTabIndexProvider>
                        </ResizeContext.Provider>
                    </UserMenuContext.Provider>
                </MainNavigationContext.Provider>
            </NavigationBarStaticWrap>
        </StyledNavigationBar>
    )
}
/**
 * The NavigationBar implements the [design system specification](https://design.planview.com/components/navigation/navigation-bar/anatomy)
 *
 * `import { NavigationBar } from '@planview/pv-toolbar'`
 *
 * ### Accessibility
 * This component will add a [navigation landmark](https://www.w3.org/WAI/ARIA/apg/patterns/landmarks/examples/navigation.html) to your application which will serve as a single tab-stop for easy keyboard navigation.
 * Having [landmarks](https://www.w3.org/WAI/ARIA/apg/practices/landmark-regions/) will help user using assistive technology jump quicker between the different landmarks on the page.
 *
 * If you have more than one navigation on your page at the same time it is considered good practice to add `aria-label` attributes on the navigation landmarks
 *
 *
 */
export const NavigationBar = React.forwardRef(NavigationBarImpl)
