import { CreateLinkEvent, Dispose, DropBounce, EaseOut, FindNewFriendsMessageComposer, JumpBy, Motions, OctaneToolbarAnimateIconEvent, PerkAllowancesMessageEvent, PerkEnum, Queue, Wait, YouTubeRoomSettingsEvent } from '@octane/renderer';
import { AnimatePresence, motion, Variants } from 'framer-motion';
import { CSSProperties, FC, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
import { GetConfigurationValue, isHousekeepingEnabled, localizeWithFallback, MessengerIconState, OpenMessengerChat, SendMessageComposer, setYoutubeRoomEnabled, VisitDesktop } from '../../api';
import collapseLeftImg from '../../assets/images/toolbar/air/collapse-left.png';
import collapseRightImg from '../../assets/images/toolbar/air/collapse-right.png';
import dividerImg from '../../assets/images/toolbar/air/divider.png';
import memenuBgImg from '../../assets/images/toolbar/air/memenu-bg.png';
import memenuCircleImg from '../../assets/images/toolbar/air/memenu-circle.png';
import { Flex, LayoutAvatarImageView, LayoutItemCountView } from '../../common';
import { SoundboardRoomMessageEvent } from '../../events';
import { useAchievements, useBuildHeight, useDailyTasks, useFriends, useHasPermission, useInventoryUnseenTracker, useMentionsSnapshot, useMessageEvent, useMessenger, useOctaneEvent, useOpenIssueCount, useRewardTracks, useSessionInfo, useSoundboard, useUiEvent, useWiredTools } from '../../hooks';
import { BottomDockLayout, resolveBottomDockLayout } from './bottomDockLayout';
import { ToolbarItemView } from './ToolbarItemView';
import { ToolbarMeView } from './ToolbarMeView';
import { ToolbarNewAdditionsLabel } from './ToolbarNewAdditionsLabel';
import { ToolbarProgressionView } from './ToolbarProgressionView';
import { useGroupForumUnreadStore } from '../../state/groupForumUnreadStore';
import { YouTubePlayerView } from './YouTubePlayerView';
import { BaseButton } from '../../common/BaseButton';
import { NativeTextTree } from '../../common/native-text/NativeTextTree';

const containerVariants: Variants = {
    hidden: { transition: { staggerChildren: 0.015, staggerDirection: -1 } },
    visible: { transition: { staggerChildren: 0.025 } }
};
const itemVariants: Variants = {
    hidden: { opacity: 0, y: 10, scale: 0.8 },
    visible: { opacity: 1, y: 0, scale: 1, transition: { type: 'spring', stiffness: 400, damping: 22 } }
};

const shellVariants: Variants = {
    hidden: { opacity: 0, y: 8 },
    visible: { opacity: 1, y: 0 }
};

const SHELL_TRANSITION = { type: 'spring' as const, stiffness: 260, damping: 26 };
const NAV_TRANSITION = { type: 'spring' as const, stiffness: 300, damping: 28 };
const ME_POPOVER_TRANSITION = { type: 'spring' as const, stiffness: 420, damping: 28 };
const LEFT_COLLAPSED_STORAGE_KEY = 'nitro.toolbar.leftCollapsed';
const RIGHT_COLLAPSED_STORAGE_KEY = 'nitro.toolbar.rightCollapsed';


const readCollapsedPreference = (key: string): boolean =>
{
    if(typeof window === 'undefined') return false;

    try
    {
        return window.localStorage.getItem(key) === '1';
    }
    catch
    {
        return false;
    }
};

export const ToolbarView: FC<{ isInRoom: boolean }> = props =>
{
    const { isInRoom } = props;
    const [ isMeExpanded, setMeExpanded ] = useState(false);
    const [ isProgressionExpanded, setProgressionExpanded ] = useState(false);
    const [ isTouchLayout, setIsTouchLayout ] = useState(false);
    const [ leftCollapsed, setLeftCollapsed ] = useState(() => readCollapsedPreference(LEFT_COLLAPSED_STORAGE_KEY));
    const [ rightCollapsed, setRightCollapsed ] = useState(() => readCollapsedPreference(RIGHT_COLLAPSED_STORAGE_KEY));
    const [ dockLayout, setDockLayout ] = useState<BottomDockLayout>({ chatRaised: false, chatBottom: 7 });
    const [ staffStackBottom, setStaffStackBottom ] = useState<number | null>(null);
    const [ useGuideTool, setUseGuideTool ] = useState(false);
    const [ youtubeEnabled, setYoutubeEnabled ] = useState(false);
    const [ soundboardPulse, setSoundboardPulse ] = useState(false);
    const soundboardPulseTimerRef = useRef<number | null>(null);
    const leftDockRef = useRef<HTMLDivElement>(null);
    const rightDockRef = useRef<HTMLDivElement>(null);
    const { userFigure = null } = useSessionInfo();
    const { getFullCount = 0 } = useInventoryUnseenTracker();
    const { getTotalUnseen = 0 } = useAchievements();
    const { unseenCount: unseenDailyTaskCount = 0 } = useDailyTasks();
    const { unseenCount: unseenRewardTrackCount = 0 } = useRewardTracks();
    // HabboToolbar.setUnseenItemCount("HTIE_ICON_PROGRESSION", unseenProgMenuCount): achievements + daily tasks + reward track rewards.
    const unreadForumsCount = useGroupForumUnreadStore((state) => state.unreadForumsCount);
    const unseenProgMenuCount = getTotalUnseen + unseenDailyTaskCount + unseenRewardTrackCount;
    // The Me icon also counts the forums with unread messages (shown on the Forums entry of the Me menu).
    const meMenuCount = unseenProgMenuCount + unreadForumsCount;
    const { requests = [] } = useFriends();
    const { iconState = MessengerIconState.HIDDEN, acknowledgeIcon = null } = useMessenger();

    // AIR HabboFriendBarView.onOpenMessenger: toggle the messenger and stop the icon blinking.
    const openMessenger = () =>
    {
        acknowledgeIcon?.();
        OpenMessengerChat();
    };
    const { unreadCount: mentionsUnread = 0 } = useMentionsSnapshot();
    const mentionsEnabled = useMemo(() => GetConfigurationValue<boolean>('mentions_ui.enabled', true), []);
    const buildersClubEnabled = useMemo(() => GetConfigurationValue<boolean>('buildersclub.enabled', GetConfigurationValue<boolean>('toolbar.buildersclub.enabled', true)), []);
    const fortuneWheelEnabled = useMemo(() => GetConfigurationValue<boolean>('toolbar.fortunewheel.enabled', true), []);
    const { openMonitor, showToolbarButton } = useWiredTools();
    const { enabled: soundboardEnabled, reset: resetSoundboard } = useSoundboard();
    const { available: buildHeightAvailable, toggle: toggleBuildHeight } = useBuildHeight();
    const isMod = useHasPermission('acc_supporttool');
    const isHk = useHasPermission('acc_housekeeping');
    const hkEnabled = useMemo(() => isHousekeepingEnabled(), []);
    // AIR: the moderator button opens the start panel (the init message already opened it once) and counts the open issues of the issue manager
    const openIssueCount = useOpenIssueCount();
    const openTicketsCount = isMod ? openIssueCount : 0;
    const visibilityVariant = 'visible';
    const touchLayout = isTouchLayout;
    const mobileOnlyClasses = touchLayout ? '' : 'hidden';
    const desktopBlockClasses = touchLayout ? 'hidden' : 'block';
    const desktopFlexClasses = touchLayout ? 'hidden' : 'flex';
    const socialInSideStack = touchLayout;
    const sideStackClasses = touchLayout ? '' : 'hidden';
    const storiesEnabled = useMemo(() => GetConfigurationValue<boolean>('toolbar.stories.enabled', false), []);
    const [ messengerNotifyFrame, setMessengerNotifyFrame ] = useState(0);
    const chatFrameStyle = useMemo<CSSProperties | undefined>(() =>
    {
        if(touchLayout) return undefined;

        return { bottom: `${ dockLayout.chatBottom }px` };
    }, [ dockLayout.chatBottom, touchLayout ]);

    const railMaxWidthClass = (isInRoom && !dockLayout.chatRaised) ? 'max-w-[calc(50vw-242px)]' : 'max-w-[calc(50vw-12px)]';
    const chatFramePositionClass = touchLayout ? 'bottom-[90px]' : '';
    const leftNavVariants = useMemo<Variants>(() => ({
        hidden: { opacity: 0, x: isInRoom ? -10 : 0, y: isInRoom ? 0 : 8, pointerEvents: 'none' },
        visible: { opacity: 1, x: 0, y: 0, pointerEvents: 'auto' }
    }), [ isInRoom ]);
    const rightNavVariants = useMemo<Variants>(() => ({
        hidden: { opacity: 0, x: 10, pointerEvents: 'none' },
        visible: { opacity: 1, x: 0, pointerEvents: 'auto' }
    }), []);
    const mobileNavVariants = useMemo<Variants>(() => ({
        hidden: { opacity: 0, y: 8, pointerEvents: 'none' },
        visible: { opacity: 1, y: 0, pointerEvents: 'auto' }
    }), []);

    useMessageEvent<YouTubeRoomSettingsEvent>(YouTubeRoomSettingsEvent, event =>
    {
        const enabled = event.getParser().youtubeEnabled;
        setYoutubeEnabled(enabled);
        setYoutubeRoomEnabled(enabled);
    });

    useUiEvent<SoundboardRoomMessageEvent>(SoundboardRoomMessageEvent.ROOM_MESSAGE, () =>
    {
        setSoundboardPulse(true);
        if(soundboardPulseTimerRef.current !== null) window.clearTimeout(soundboardPulseTimerRef.current);
        soundboardPulseTimerRef.current = window.setTimeout(() =>
        {
            setSoundboardPulse(false);
            soundboardPulseTimerRef.current = null;
        }, 700);
    });

    useEffect(() => () =>
    {
        if(soundboardPulseTimerRef.current !== null) window.clearTimeout(soundboardPulseTimerRef.current);
    }, []);

    useEffect(() =>
    {
        if(!isInRoom)
        {
            setYoutubeEnabled(false);
            setYoutubeRoomEnabled(false);
            resetSoundboard();
        }
    }, [ isInRoom, resetSoundboard ]);

    useEffect(() =>
    {
        const query = window.matchMedia('(pointer: coarse), (hover: none)');
        const updateTouchLayout = () => setIsTouchLayout(query.matches);

        updateTouchLayout();
        query.addEventListener('change', updateTouchLayout);

        return () => query.removeEventListener('change', updateTouchLayout);
    }, []);

    useEffect(() =>
    {
        if(iconState !== MessengerIconState.UNREAD)
        {
            setMessengerNotifyFrame(0);
            return;
        }

        const interval = window.setInterval(() => setMessengerNotifyFrame(value => (value === 0 ? 1 : 0)), 500);

        return () => window.clearInterval(interval);
    }, [ iconState ]);

    useEffect(() =>
    {
        try
        {
            window.localStorage.setItem(LEFT_COLLAPSED_STORAGE_KEY, leftCollapsed ? '1' : '0');
        }
        catch
        {
        }
    }, [ leftCollapsed ]);

    useEffect(() =>
    {
        try
        {
            window.localStorage.setItem(RIGHT_COLLAPSED_STORAGE_KEY, rightCollapsed ? '1' : '0');
        }
        catch
        {
        }
    }, [ rightCollapsed ]);

    useLayoutEffect(() =>
    {
        if(touchLayout || !isInRoom) return;

        const leftDock = leftDockRef.current;
        const rightDock = rightDockRef.current;

        if(!leftDock || !rightDock) return;

        let frame = 0;

        const applyMeasurement = () =>
        {
            const leftRect = leftDock.getBoundingClientRect();
            const rightRect = rightDock.getBoundingClientRect();
            const leftEdge = leftRect.left + Math.max(leftRect.width, leftDock.scrollWidth);
            const rightEdge = rightRect.right - Math.max(rightRect.width, rightDock.scrollWidth);
            const next = resolveBottomDockLayout({
                viewportWidth: window.innerWidth,
                leftEdge,
                rightEdge
            });

            setDockLayout(previous => (
                previous.chatRaised === next.chatRaised && previous.chatBottom === next.chatBottom
                    ? previous
                    : next
            ));
        };

        const measure = () =>
        {
            window.cancelAnimationFrame(frame);
            frame = window.requestAnimationFrame(applyMeasurement);
        };

        applyMeasurement();

        const observer = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(measure);

        observer?.observe(leftDock);
        observer?.observe(rightDock);
        observer?.observe(document.body);
        window.addEventListener('resize', measure);

        return () =>
        {
            window.cancelAnimationFrame(frame);
            observer?.disconnect();
            window.removeEventListener('resize', measure);
        };
    }, [
        buildHeightAvailable,
        buildersClubEnabled,
        fortuneWheelEnabled,
        hkEnabled,
        iconState,
        isHk,
        isInRoom,
        isMod,
        leftCollapsed,
        mentionsEnabled,
        rightCollapsed,
        showToolbarButton,
        soundboardEnabled,
        touchLayout,
        youtubeEnabled
    ]);

    useEffect(() =>
    {
        const measure = () =>
        {
            const roomTools = document.querySelector('.octane-room-tools-container') as HTMLElement | null;
            const next = roomTools
                ? Math.max(8, Math.round(window.innerHeight - roomTools.getBoundingClientRect().top + 15))
                : null;

            setStaffStackBottom(prevValue => (prevValue === next ? prevValue : next));
        };

        measure();

        const interval = window.setInterval(measure, 400);
        window.addEventListener('resize', measure);

        return () =>
        {
            window.clearInterval(interval);
            window.removeEventListener('resize', measure);
        };
    }, [ isInRoom ]);

    const openYouTubePlayer = () => window.dispatchEvent(new CustomEvent('youtube:toggle'));

    useMessageEvent<PerkAllowancesMessageEvent>(PerkAllowancesMessageEvent, event =>
    {
        setUseGuideTool(event.getParser().isAllowed(PerkEnum.USE_GUIDE_TOOL));
    });

    useOctaneEvent<OctaneToolbarAnimateIconEvent>(OctaneToolbarAnimateIconEvent.ANIMATE_ICON, event =>
    {
        const animationIconToToolbar = (iconName: string, image: HTMLImageElement, x: number, y: number) =>
        {
            const target = (document.body.getElementsByClassName(iconName)[0] as HTMLElement);

            if(!target) return;

            image.className = 'toolbar-icon-animation';
            image.style.visibility = 'visible';
            image.style.left = (x + 'px');
            image.style.top = (y + 'px');

            document.body.append(image);

            const targetBounds = target.getBoundingClientRect();
            const imageBounds = image.getBoundingClientRect();
            const left = (imageBounds.x - targetBounds.x);
            const top = (imageBounds.y - targetBounds.y);
            const squared = Math.sqrt(((left * left) + (top * top)));
            const wait = (500 - Math.abs(((((1 / squared) * 100) * 500) * 0.5)));
            const height = 20;
            const motionName = (`ToolbarBouncing[${ iconName }]`);

            if(!Motions.getMotionByTag(motionName))
            {
                Motions.runMotion(new Queue(new Wait((wait + 8)), new DropBounce(target, 400, 12))).tag = motionName;
            }

            const motion = new Queue(new EaseOut(new JumpBy(image, wait, ((targetBounds.x - imageBounds.x) + height), (targetBounds.y - imageBounds.y), 100, 1), 1), new Dispose(image));

            Motions.runMotion(motion);
        };

        animationIconToToolbar('icon-inventory', event.image, event.x, event.y);
    });

    return (
        <NativeTextTree>
            <>
                { youtubeEnabled && <YouTubePlayerView /> }

                { isInRoom &&
                    <div
                        data-chat-raised={ dockLayout.chatRaised ? 'true' : 'false' }
                        style={ chatFrameStyle }
                        className={ `tb-frame absolute ${ chatFramePositionClass } left-1/2 -translate-x-1/2 z-[71] flex h-[38px] w-[466px] max-w-[95vw] items-center p-0 pointer-events-none` }>
                        <Flex
                            alignItems="center"
                            justifyContent="center"
                            className="pointer-events-auto h-full w-full min-w-0 flex-1"
                            id="toolbar-chat-input-container" />
                    </div> }

                <motion.div
                    initial="visible"
                    animate={ visibilityVariant }
                    variants={ shellVariants }
                    transition={ SHELL_TRANSITION }
                    className={ `octane-toolbar octane-toolbar-hobba absolute bottom-0 left-0 right-0 z-[70] h-[46px] ${ desktopBlockClasses }` } />

                <motion.div
                    ref={ leftDockRef }
                    initial="visible"
                    animate={ visibilityVariant }
                    variants={ leftNavVariants }
                    transition={ NAV_TRANSITION }
                    className={ `tb-nav-clip absolute bottom-0 left-0 z-[71] h-[46px] ${ railMaxWidthClass } items-center ${ desktopFlexClasses }` }>
                    <BaseButton
                        type="button"
                        onClick={ () => setLeftCollapsed(value => !value) }
                        aria-label={ localizeWithFallback('toolbar.icons.toggle', 'Show/hide icons') }
                        className="tb-collapse pointer-events-auto">
                        <img src={ leftCollapsed ? collapseRightImg : collapseLeftImg } alt="" />
                    </BaseButton>
                    <motion.div
                        variants={ containerVariants }
                        className="tb-open-shell flex h-[46px] max-w-full items-start overflow-visible bg-transparent">
                        { !leftCollapsed && (<>
                        <motion.div variants={ itemVariants } className="tb-slot">
                            { isInRoom
                                ? <ToolbarItemView icon="habbo" onClick={ () => VisitDesktop() } className="tb-icon" />
                                : <ToolbarItemView icon="house" onClick={ () => CreateLinkEvent('navigator/goto/home') } className="tb-icon" /> }
                        </motion.div>
                        <motion.div variants={ itemVariants } className="tb-slot">
                            <ToolbarItemView icon="rooms" onClick={ () => CreateLinkEvent('navigator/toggle') } className="tb-icon" />
                        </motion.div>
                        { isInRoom &&
                            <motion.div variants={ itemVariants } className="relative tb-slot tb-slot-progression">
                                <AnimatePresence>
                                    { isProgressionExpanded &&
                                        <motion.div
                                            initial={ { opacity: 0, y: 6, scale: 0.97 } }
                                            animate={ { opacity: 1, y: 0, scale: 1 } }
                                            exit={ { opacity: 0, y: 6, scale: 0.97 } }
                                            transition={ ME_POPOVER_TRANSITION }
                                            className="pointer-events-auto absolute bottom-[calc(100%+8px)] left-0 z-50">
                                            <ToolbarProgressionView
                                                setExpanded={ setProgressionExpanded }
                                                unseenAchievementCount={ getTotalUnseen }
                                                unseenDailyTaskCount={ unseenDailyTaskCount }
                                                unseenRewardTrackCount={ unseenRewardTrackCount } />
                                        </motion.div> }
                                </AnimatePresence>
                                <ToolbarItemView
                                    icon="progression"
                                    onClick={ event =>
                                    {
                                        setProgressionExpanded(value => !value);
                                        event.stopPropagation();
                                    } }
                                    className="tb-icon" />
                                { (unseenProgMenuCount > 0) &&
                                    <LayoutItemCountView count={ unseenProgMenuCount } className="octane-toolbar-count pointer-events-none absolute -right-1 top-0" /> }
                            </motion.div> }
                        { GetConfigurationValue('game.center.enabled') &&
                            <motion.div variants={ itemVariants } className="tb-slot">
                                <ToolbarItemView icon="game" onClick={ () => CreateLinkEvent('games/toggle') } className="tb-icon" />
                            </motion.div> }
                        { (!isInRoom && storiesEnabled) &&
                            <motion.div variants={ itemVariants } className="tb-slot">
                                <ToolbarItemView icon="stories" onClick={ () => CreateLinkEvent('stories/toggle') } className="tb-icon" />
                            </motion.div> }
                        </>) }
                        <motion.div variants={ itemVariants } className="tb-slot">
                            <ToolbarItemView icon="catalog" onClick={ () => CreateLinkEvent('catalog/toggle/normal') } className="tb-icon" />
                            <ToolbarNewAdditionsLabel />
                        </motion.div>
                        { (!leftCollapsed && buildersClubEnabled) &&
                            <motion.div variants={ itemVariants } className="tb-slot">
                                <ToolbarItemView icon="buildersclub" onClick={ () => CreateLinkEvent('catalog/toggle/builder') } className="tb-icon" />
                            </motion.div> }
                        { (!leftCollapsed && isInRoom) &&
                            <motion.div variants={ itemVariants } className="relative tb-slot tb-slot-inventory">
                                <ToolbarItemView icon="inventory" onClick={ () => CreateLinkEvent('inventory/toggle') } className="tb-icon" />
                                { (getFullCount > 0) &&
                                    <LayoutItemCountView count={ getFullCount } className="octane-toolbar-count absolute -right-1 top-0" /> }
                            </motion.div> }
                        { !leftCollapsed &&
                        <motion.div variants={ itemVariants } className="relative tb-slot tb-slot-tall tb-slot-memenu">
                            <img src={ memenuBgImg } alt="" className="tb-memenu-bg" />
                            <AnimatePresence>
                                { isMeExpanded &&
                                    <motion.div
                                        initial={ { opacity: 0, y: 6, scale: 0.97 } }
                                        animate={ { opacity: 1, y: 0, scale: 1 } }
                                        exit={ { opacity: 0, y: 6, scale: 0.97 } }
                                        transition={ ME_POPOVER_TRANSITION }
                                        className="pointer-events-auto absolute bottom-[calc(100%+8px)] left-1/2 z-50 -translate-x-1/2">
                                        <ToolbarMeView setMeExpanded={ setMeExpanded } unseenAchievementCount={ getTotalUnseen } useGuideTool={ useGuideTool } />
                                    </motion.div> }
                            </AnimatePresence>
                            <motion.div
                                className="tb-memenu-avatar"
                                onClick={ event =>
                                {
                                    setMeExpanded(value => !value);
                                    event.stopPropagation();
                                } }>
                                <LayoutAvatarImageView airMeMenu={ true } direction={ 3 } figure={ userFigure } />
                            </motion.div>
                            <img src={ memenuCircleImg } alt="" className="tb-memenu-circle" />
                            { (meMenuCount > 0) &&
                                <LayoutItemCountView count={ meMenuCount } className="octane-toolbar-count pointer-events-none absolute -right-1 -top-1 z-10" /> }
                        </motion.div> }
                        { (!leftCollapsed && isInRoom && showToolbarButton) &&
                            <motion.div variants={ itemVariants } className="tb-slot tb-slot-tall">
                                <ToolbarItemView icon="wired-tools" onClick={ openMonitor } className="tb-icon" />
                            </motion.div> }
                        { isInRoom &&
                            <motion.div variants={ itemVariants } className="tb-slot tb-slot-tall">
                                <ToolbarItemView icon="camera" onClick={ () => CreateLinkEvent('camera/toggle') } className="tb-icon" />
                            </motion.div> }
                        <img src={ dividerImg } alt="" className="tb-divider" />
                        { !leftCollapsed && (<>
                        { fortuneWheelEnabled &&
                            <motion.div variants={ itemVariants } className="tb-slot tb-slot-fit">
                                <ToolbarItemView icon="fortune-wheel" onClick={ () => CreateLinkEvent('fortune-wheel/toggle') } className="tb-icon" />
                            </motion.div> }
                        { (isInRoom && youtubeEnabled) &&
                            <motion.div variants={ itemVariants } className="tb-slot tb-slot-fit">
                                <ToolbarItemView icon="youtube" onClick={ openYouTubePlayer } className="tb-icon" />
                            </motion.div> }
                        { (isInRoom && soundboardEnabled) &&
                            <motion.div variants={ itemVariants } className="tb-slot tb-slot-fit">
                                <ToolbarItemView icon="soundboard" onClick={ () => CreateLinkEvent('soundboard/toggle') } className={ `tb-icon ${ soundboardPulse ? 'animate-pulse' : '' }` } />
                            </motion.div> }
                        { (isInRoom && buildHeightAvailable) &&
                            <motion.div variants={ itemVariants } className="tb-slot tb-slot-fit">
                                <ToolbarItemView icon="buildheight" onClick={ toggleBuildHeight } className="tb-icon" />
                            </motion.div> }
                        { isMod &&
                            <motion.div variants={ itemVariants } className="relative tb-slot tb-slot-fit">
                                <ToolbarItemView icon="modtools" onClick={ () => CreateLinkEvent('mod-tools/show') } className="tb-icon" />
                                { (openTicketsCount > 0) &&
                                    <LayoutItemCountView count={ openTicketsCount } className="octane-toolbar-count pointer-events-none absolute -right-1 -top-1 z-10" /> }
                            </motion.div> }
                        { (isHk && hkEnabled) &&
                            <motion.div variants={ itemVariants } className="tb-slot tb-slot-fit">
                                <ToolbarItemView icon="housekeeping" onClick={ () => CreateLinkEvent('housekeeping/toggle') } className="tb-icon" />
                            </motion.div> }
                        </>) }
                    </motion.div>
                </motion.div>
                <motion.div
                    ref={ rightDockRef }
                    initial="visible"
                    animate={ visibilityVariant }
                    variants={ rightNavVariants }
                    transition={ NAV_TRANSITION }
                    className={ `tb-nav-clip absolute bottom-0 z-[71] h-[46px] ${ railMaxWidthClass } items-center ${ desktopFlexClasses } ${ isInRoom ? 'right-0' : 'right-3' }` }>
                    <motion.div
                        variants={ containerVariants }
                        className="tb-open-shell tb-open-shell-right flex h-[46px] max-w-full items-start overflow-visible bg-transparent">
                        <img src={ dividerImg } alt="" className="tb-divider" />
                        <motion.div variants={ itemVariants } className="relative tb-slot">
                            <ToolbarItemView icon="friendall" onClick={ () => CreateLinkEvent('friends/toggle') } className="tb-icon" />
                            { (requests.length > 0) &&
                                <LayoutItemCountView count={ requests.length } className="octane-toolbar-count absolute -right-2 -top-1" /> }
                        </motion.div>
                        <motion.div variants={ itemVariants } className="tb-slot">
                            <ToolbarItemView icon="friendsearch" onClick={ () => SendMessageComposer(new FindNewFriendsMessageComposer()) } className="tb-icon" />
                        </motion.div>
                        { (iconState !== MessengerIconState.HIDDEN) &&
                        <motion.div variants={ itemVariants } className="tb-slot tb-slot-messenger">
                            <ToolbarItemView className={ `tb-icon ${ iconState === MessengerIconState.UNREAD ? (messengerNotifyFrame === 1 ? 'is-notify-1' : 'is-notify-0') : '' }` } icon="message" onClick={ openMessenger } />
                        </motion.div> }
                        { !rightCollapsed && (<>
                        { mentionsEnabled &&
                            <motion.div variants={ itemVariants } className="relative tb-slot">
                                <ToolbarItemView icon={ mentionsUnread > 0 ? 'mentions-unread' : 'mentions' } onClick={ () => CreateLinkEvent('mentions/toggle') } className="tb-icon" />
                            </motion.div> }
                        <div className={ `h-full shrink-0 ${ desktopBlockClasses }` } id="toolbar-friend-bar-container-desktop" />
                        </>) }
                    </motion.div>
                    <BaseButton
                        type="button"
                        onClick={ () => setRightCollapsed(value => !value) }
                        aria-label={ localizeWithFallback('toolbar.icons.toggle', 'Show/hide icons') }
                        className="tb-collapse pointer-events-auto">
                        <img src={ rightCollapsed ? collapseLeftImg : collapseRightImg } alt="" />
                    </BaseButton>
                </motion.div>
                <motion.div
                    initial="visible"
                    animate={ visibilityVariant }
                    variants={ mobileNavVariants }
                    transition={ NAV_TRANSITION }
                    className={ `absolute left-1/2 bottom-0 z-[71] flex w-[95vw] -translate-x-1/2 items-center overflow-visible ${ mobileOnlyClasses } ${ isInRoom ? 'octane-toolbar-mobile-hobba px-[6px] py-[4px] mb-[3px]' : '' }` }>
                    <motion.div
                        variants={ containerVariants }
                        className="tb-bar-scroll flex h-full min-w-0 flex-1 items-center gap-2 overflow-x-auto overflow-y-visible px-1">
                        <motion.div variants={ itemVariants }>
                            { isInRoom
                                ? <ToolbarItemView icon="habbo" onClick={ () => VisitDesktop() } className="tb-icon" />
                                : <ToolbarItemView icon="house" onClick={ () => CreateLinkEvent('navigator/goto/home') } className="tb-icon" /> }
                        </motion.div>
                        <motion.div variants={ itemVariants }>
                            <ToolbarItemView icon="rooms" onClick={ () => CreateLinkEvent('navigator/toggle') } className="tb-icon" />
                        </motion.div>
                        { GetConfigurationValue('game.center.enabled') &&
                            <motion.div variants={ itemVariants }>
                                <ToolbarItemView icon="game" onClick={ () => CreateLinkEvent('games/toggle') } className="tb-icon" />
                            </motion.div> }
                        <motion.div variants={ itemVariants } className="relative">
                            <ToolbarItemView icon="catalog" onClick={ () => CreateLinkEvent('catalog/toggle/normal') } className="tb-icon" />
                            <ToolbarNewAdditionsLabel />
                        </motion.div>
                        <motion.div variants={ itemVariants } className="relative tb-slot tb-slot-tall tb-slot-memenu shrink-0">
                            <img src={ memenuBgImg } alt="" className="tb-memenu-bg" />
                            <AnimatePresence>
                                { isMeExpanded &&
                                    <motion.div
                                        initial={ { opacity: 0, y: 6, scale: 0.97 } }
                                        animate={ { opacity: 1, y: 0, scale: 1 } }
                                        exit={ { opacity: 0, y: 6, scale: 0.97 } }
                                        transition={ ME_POPOVER_TRANSITION }
                                        className="pointer-events-auto fixed bottom-[calc(100%+10px)] left-1/2 z-[70] -translate-x-1/2">
                                        <ToolbarMeView setMeExpanded={ setMeExpanded } unseenAchievementCount={ getTotalUnseen } useGuideTool={ useGuideTool } />
                                    </motion.div> }
                            </AnimatePresence>
                            <motion.div
                                className="tb-memenu-avatar"
                                onClick={ event =>
                                {
                                    setMeExpanded(value => !value);
                                    event.stopPropagation();
                                } }>
                                <LayoutAvatarImageView airMeMenu={ true } direction={ 3 } figure={ userFigure } />
                            </motion.div>
                            <img src={ memenuCircleImg } alt="" className="tb-memenu-circle" />
                            { (meMenuCount > 0) &&
                                <LayoutItemCountView count={ meMenuCount } className="octane-toolbar-count pointer-events-none absolute -right-1 -top-1 z-10" /> }
                        </motion.div>
                        { isInRoom &&
                            <motion.div variants={ itemVariants } className="relative">
                                <ToolbarItemView icon="inventory" onClick={ () => CreateLinkEvent('inventory/toggle') } className="tb-icon" />
                                { (getFullCount > 0) &&
                                    <LayoutItemCountView count={ getFullCount } className="octane-toolbar-count absolute -right-1 top-0" /> }
                            </motion.div> }
                        { fortuneWheelEnabled &&
                            <motion.div variants={ itemVariants }>
                                <ToolbarItemView icon="fortune-wheel" onClick={ () => CreateLinkEvent('fortune-wheel/toggle') } className="tb-icon" />
                            </motion.div> }
                    </motion.div>
                    <motion.div
                        variants={ containerVariants }
                        className="tb-bar-scroll flex h-full items-center gap-2 overflow-x-auto overflow-y-visible px-1">
                        { (isInRoom && showToolbarButton) &&
                            <motion.div variants={ itemVariants }>
                                <ToolbarItemView icon="wired-tools" onClick={ openMonitor } className="tb-icon" />
                            </motion.div> }
                        { (isInRoom && youtubeEnabled) &&
                            <motion.div variants={ itemVariants }>
                                <ToolbarItemView icon="youtube" onClick={ openYouTubePlayer } className="tb-icon" />
                            </motion.div> }
                        { (isInRoom && soundboardEnabled) &&
                            <motion.div variants={ itemVariants }>
                                <ToolbarItemView icon="soundboard" onClick={ () => CreateLinkEvent('soundboard/toggle') } className={ `tb-icon ${ soundboardPulse ? 'animate-pulse' : '' }` } />
                            </motion.div> }
                        { (isInRoom && buildHeightAvailable) &&
                            <motion.div variants={ itemVariants }>
                                <ToolbarItemView icon="buildheight" onClick={ toggleBuildHeight } className="tb-icon" />
                            </motion.div> }
                        { /* On narrow desktop windows the social icons live in the
                             left side stack — only real touch devices get them here. */ }
                        { !socialInSideStack &&
                            <motion.div variants={ itemVariants } className="relative">
                                <ToolbarItemView icon="friendall" onClick={ () => CreateLinkEvent('friends/toggle') } className="tb-icon" />
                                { (requests.length > 0) &&
                                    <LayoutItemCountView count={ requests.length } className="octane-toolbar-count absolute -right-2 -top-1" /> }
                            </motion.div> }
                        { (!socialInSideStack && mentionsEnabled) &&
                            <motion.div variants={ itemVariants } className="relative">
                                <ToolbarItemView icon={ mentionsUnread > 0 ? 'mentions-unread' : 'mentions' } onClick={ () => CreateLinkEvent('mentions/toggle') } className="tb-icon" />
                            </motion.div> }
                    </motion.div>
                </motion.div>
                { /* Mobile side tools — moved out of the bottom bar into a
                     vertical pill stack on the left edge so the bottom bar has
                     room. Optional Builders Club, plus camera in-room
                     and the staff-only tools when permitted. */ }
                <motion.div
                    initial="visible"
                    animate={ visibilityVariant }
                    variants={ mobileNavVariants }
                    transition={ NAV_TRANSITION }
                    style={ staffStackBottom != null ? { top: 'auto', bottom: `${ staffStackBottom }px` } : undefined }
                    className={ `absolute left-1 z-[71] flex flex-col items-center gap-[2px] bg-[#55534e] px-[2px] py-[4px] ${ staffStackBottom == null ? 'top-1/2 -translate-y-1/2' : '' } ${ sideStackClasses }` }>
                    { touchLayout && buildersClubEnabled &&
                        <motion.div variants={ itemVariants }>
                            <ToolbarItemView icon="buildersclub" onClick={ () => CreateLinkEvent('catalog/toggle/builder') } className="tb-icon" />
                        </motion.div> }
                    { isInRoom &&
                        <motion.div variants={ itemVariants }>
                            <ToolbarItemView icon="camera" onClick={ () => CreateLinkEvent('camera/toggle') } className="tb-icon" />
                        </motion.div> }
                    { isMod &&
                        <motion.div variants={ itemVariants } className="relative">
                            <ToolbarItemView icon="modtools" onClick={ () => CreateLinkEvent('mod-tools/show') } className="tb-icon" />
                            { (openTicketsCount > 0) &&
                                <LayoutItemCountView count={ openTicketsCount } className="octane-toolbar-count pointer-events-none absolute -right-1 -top-1 z-10" /> }
                        </motion.div> }
                    { (isHk && hkEnabled) &&
                        <motion.div variants={ itemVariants }>
                            <ToolbarItemView icon="housekeeping" onClick={ () => CreateLinkEvent('housekeeping/toggle') } className="tb-icon" />
                        </motion.div> }
                    { /* Below the compact breakpoint the right rail's social icons
                         live in the stack — on narrow desktop windows too, so they
                         don't jump back into the bottom bar. Real touch devices
                         keep friends + mentions in the mobile bar instead. */ }
                    { socialInSideStack &&
                        <motion.div variants={ itemVariants } className="relative">
                            <ToolbarItemView icon="friendall" onClick={ () => CreateLinkEvent('friends/toggle') } className="tb-icon" />
                            { (requests.length > 0) &&
                                <LayoutItemCountView count={ requests.length } className="octane-toolbar-count pointer-events-none absolute -right-1 -top-1 z-10" /> }
                        </motion.div> }
                    { socialInSideStack &&
                        <motion.div variants={ itemVariants }>
                            <ToolbarItemView icon="friendsearch" onClick={ () => SendMessageComposer(new FindNewFriendsMessageComposer()) } className="tb-icon" />
                        </motion.div> }
                    { (socialInSideStack && mentionsEnabled) &&
                        <motion.div variants={ itemVariants } className="relative">
                            <ToolbarItemView icon={ mentionsUnread > 0 ? 'mentions-unread' : 'mentions' } onClick={ () => CreateLinkEvent('mentions/toggle') } className="tb-icon" />
                        </motion.div> }
                    { (socialInSideStack && ((iconState === MessengerIconState.SHOW) || (iconState === MessengerIconState.UNREAD))) &&
                        <motion.div variants={ itemVariants }>
                            <ToolbarItemView className={ `tb-icon ${ iconState === MessengerIconState.UNREAD ? (messengerNotifyFrame === 1 ? 'is-notify-1' : 'is-notify-0') : '' }` } icon="message" onClick={ openMessenger } />
                        </motion.div> }
                </motion.div>
            </>
        </NativeTextTree>
    );
};
