import React, { MouseEventHandler, forwardRef, useState } from 'react';
import FocusTrap from 'focus-trap-react';
import {
  Box,
  Avatar,
  Text,
  Overlay,
  OverlayCenter,
  OverlayBackdrop,
  IconButton,
  Icon,
  Icons,
  Tooltip,
  TooltipProvider,
  Menu,
  MenuItem,
  toRem,
  config,
  Line,
  PopOut,
  RectCords,
  Badge,
  Chip,
  Spinner,
  Button,
} from 'folds';
import { useAtom } from 'jotai';
import { useNavigate } from 'react-router-dom';
import { Room } from 'matrix-js-sdk';
import { useStateEvent } from '../../hooks/useStateEvent';
import { PageHeader } from '../../components/page';
import { RoomAvatar, RoomIcon } from '../../components/room-avatar';
import { UseStateProvider } from '../../components/UseStateProvider';
import { RoomTopicViewer } from '../../components/room-topic-viewer';
import { StateEvent } from '../../../types/matrix/room';
import { useMatrixClient } from '../../hooks/useMatrixClient';
import { useIsDirectRoom, useRoom } from '../../hooks/useRoom';
import { useSetting } from '../../state/hooks/settings';
import { settingsAtom } from '../../state/settings';
import { useSpaceOptionally } from '../../hooks/useSpace';
import { getHomeSearchPath, getSpaceSearchPath, withSearchParam } from '../../pages/pathUtils';
import { getCanonicalAliasOrRoomId, mxcUrlToHttp } from '../../utils/matrix';
import { getStateEvents } from '../../utils/room';
import { _SearchPathSearchParams } from '../../pages/paths';
import * as css from './RoomViewHeader.css';
import { useRoomUnread } from '../../state/hooks/unread';
import { usePowerLevelsContext } from '../../hooks/usePowerLevels';
import { markAsRead } from '../../utils/notifications';
import { roomToUnreadAtom } from '../../state/room/roomToUnread';
import { LeaveRoomPrompt } from '../../components/leave-room-prompt';
import { useRoomAvatar, useLocalRoomName, useRoomTopic } from '../../hooks/useRoomMeta';
import { ScreenSize, useScreenSizeContext } from '../../hooks/useScreenSize';
import { stopPropagation } from '../../utils/keyboard';
import { BackRouteHandler } from '../../components/BackRouteHandler';
import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
import { useRoomPinnedEvents } from '../../hooks/useRoomPinnedEvents';
import { RoomPinMenu } from './room-pin-menu';
import { useOpenRoomSettings } from '../../state/hooks/roomSettings';
import { RoomNotificationModeSwitcher } from '../../components/RoomNotificationSwitcher';
import {
  getRoomNotificationMode,
  getRoomNotificationModeIcon,
  useRoomsNotificationPreferencesContext,
} from '../../hooks/useRoomsNotificationPreferences';
import { JumpToTime } from './jump-to-time';
import { useRoomNavigate } from '../../hooks/useRoomNavigate';
import { useRoomCreators } from '../../hooks/useRoomCreators';
import { useRoomPermissions } from '../../hooks/useRoomPermissions';
import { ReportRoomModal } from './ReportRoomModal';
import { InviteUserPrompt } from '../../components/invite-user-prompt';
import { ContainerColor } from '../../styles/ContainerColor.css';
import { RoomSettingsPage } from '../../state/roomSettings';
import { useCallEmbed, useCallStart } from '../../hooks/useCallEmbed';
import { useLivekitSupport } from '../../hooks/useLivekitSupport';
import { webRTCSupported } from '../../utils/rtc';
import { mediaGalleryAtom } from '../../state/mediaGallery';
import { widgetsPanelAtom } from '../../state/widgetsPanel';
import { usePendingKnocks } from '../../hooks/usePendingKnocks';
import { bookmarksPanelAtom } from '../../state/bookmarksPanel';

type RoomMenuProps = {
  room: Room;
  requestClose: () => void;
  galleryOpen?: boolean;
  onToggleGallery?: () => void;
};
const RoomMenu = forwardRef<HTMLDivElement, RoomMenuProps>(
  ({ room, requestClose, galleryOpen, onToggleGallery }, ref) => {
    const mx = useMatrixClient();
    const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
    const screenSize = useScreenSizeContext();
    const unread = useRoomUnread(room.roomId, roomToUnreadAtom);
    const powerLevels = usePowerLevelsContext();
    const creators = useRoomCreators(room);

    const permissions = useRoomPermissions(creators, powerLevels);
    const canInvite = permissions.action('invite', mx.getSafeUserId());
    const isServerNotice = room.getType() === 'm.server_notice';
    const isCreator = creators.has(mx.getSafeUserId());
    const notificationPreferences = useRoomsNotificationPreferencesContext();
    const notificationMode = getRoomNotificationMode(notificationPreferences, room.roomId);
    const { navigateRoom } = useRoomNavigate();

    const [invitePrompt, setInvitePrompt] = useState(false);
    const [reportRoomOpen, setReportRoomOpen] = useState(false);
    const [bookmarksOpen, setBookmarksOpen] = useAtom(bookmarksPanelAtom);
    const [peopleDrawer, setPeopleDrawer] = useSetting(settingsAtom, 'isPeopleDrawer');

    const handleMarkAsRead = () => {
      markAsRead(mx, room.roomId, hideActivity);
      requestClose();
    };

    const handleInvite = () => {
      setInvitePrompt(true);
    };

    const openSettings = useOpenRoomSettings();
    const parentSpace = useSpaceOptionally();
    const handleOpenSettings = () => {
      openSettings(room.roomId, parentSpace?.roomId);
      requestClose();
    };

    return (
      <Menu ref={ref} style={{ maxWidth: toRem(160), width: '100vw' }}>
        {invitePrompt && (
          <InviteUserPrompt
            room={room}
            requestClose={() => {
              setInvitePrompt(false);
              requestClose();
            }}
          />
        )}
        {reportRoomOpen && (
          <ReportRoomModal
            roomId={room.roomId}
            onClose={() => {
              setReportRoomOpen(false);
              requestClose();
            }}
          />
        )}
        <Box direction="Column" gap="100" style={{ padding: config.space.S100 }}>
          <MenuItem
            onClick={handleMarkAsRead}
            size="300"
            after={<Icon size="100" src={Icons.CheckTwice} />}
            radii="300"
            disabled={!unread}
          >
            <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
              Mark as Read
            </Text>
          </MenuItem>
          <RoomNotificationModeSwitcher roomId={room.roomId} value={notificationMode}>
            {(handleOpen, opened, changing) => (
              <MenuItem
                size="300"
                after={
                  changing ? (
                    <Spinner size="100" variant="Secondary" />
                  ) : (
                    <Icon size="100" src={getRoomNotificationModeIcon(notificationMode)} />
                  )
                }
                radii="300"
                aria-pressed={opened}
                onClick={handleOpen}
              >
                <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
                  Notifications
                </Text>
              </MenuItem>
            )}
          </RoomNotificationModeSwitcher>
        </Box>
        <Line variant="Surface" size="300" />
        <Box direction="Column" gap="100" style={{ padding: config.space.S100 }}>
          <MenuItem
            onClick={() => {
              setBookmarksOpen((v) => !v);
              requestClose();
            }}
            size="300"
            after={<Icon size="100" src={Icons.Star} filled={bookmarksOpen} />}
            radii="300"
            aria-pressed={bookmarksOpen}
          >
            <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
              Saved Messages
            </Text>
          </MenuItem>
          {screenSize === ScreenSize.Mobile && (
            <MenuItem
              onClick={() => {
                setPeopleDrawer(!peopleDrawer);
                requestClose();
              }}
              size="300"
              after={<Icon size="100" src={Icons.User} filled={peopleDrawer} />}
              radii="300"
              aria-pressed={peopleDrawer}
            >
              <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
                Members
              </Text>
            </MenuItem>
          )}
          {screenSize === ScreenSize.Mobile && onToggleGallery && (
            <MenuItem
              onClick={() => {
                onToggleGallery();
                requestClose();
              }}
              size="300"
              after={<Icon size="100" src={Icons.Photo} filled={galleryOpen} />}
              radii="300"
              aria-pressed={galleryOpen}
            >
              <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
                Media Gallery
              </Text>
            </MenuItem>
          )}
          {!isServerNotice && (
            <MenuItem
              onClick={handleInvite}
              variant="Primary"
              fill="None"
              size="300"
              after={<Icon size="100" src={Icons.UserPlus} />}
              radii="300"
              aria-pressed={invitePrompt}
              disabled={!canInvite}
            >
              <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
                Invite
              </Text>
            </MenuItem>
          )}
          {!isServerNotice && (
            <MenuItem
              onClick={handleOpenSettings}
              size="300"
              after={<Icon size="100" src={Icons.Setting} />}
              radii="300"
            >
              <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
                Room Settings
              </Text>
            </MenuItem>
          )}
          <UseStateProvider initial={false}>
            {(promptJump, setPromptJump) => (
              <>
                <MenuItem
                  onClick={() => setPromptJump(true)}
                  size="300"
                  after={<Icon size="100" src={Icons.RecentClock} />}
                  radii="300"
                  aria-pressed={promptJump}
                >
                  <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
                    Jump to Time
                  </Text>
                </MenuItem>
                {promptJump && (
                  <JumpToTime
                    onSubmit={(eventId) => {
                      setPromptJump(false);
                      navigateRoom(room.roomId, eventId);
                      requestClose();
                    }}
                    onCancel={() => setPromptJump(false)}
                  />
                )}
              </>
            )}
          </UseStateProvider>
        </Box>
        <Line variant="Surface" size="300" />
        <Box direction="Column" gap="100" style={{ padding: config.space.S100 }}>
          {!isServerNotice && !isCreator && (
            <MenuItem
              onClick={() => setReportRoomOpen(true)}
              variant="Critical"
              fill="None"
              size="300"
              after={<Icon size="100" src={Icons.Warning} />}
              radii="300"
              aria-pressed={reportRoomOpen}
            >
              <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
                Report Room
              </Text>
            </MenuItem>
          )}
          <UseStateProvider initial={false}>
            {(promptLeave, setPromptLeave) => (
              <>
                <MenuItem
                  onClick={() => setPromptLeave(true)}
                  variant="Critical"
                  fill="None"
                  size="300"
                  after={<Icon size="100" src={Icons.ArrowGoLeft} />}
                  radii="300"
                  aria-pressed={promptLeave}
                >
                  <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
                    Leave Room
                  </Text>
                </MenuItem>
                {promptLeave && (
                  <LeaveRoomPrompt
                    roomId={room.roomId}
                    onDone={requestClose}
                    onCancel={() => setPromptLeave(false)}
                  />
                )}
              </>
            )}
          </UseStateProvider>
        </Box>
      </Menu>
    );
  },
);

type CallMenuProps = {
  onVoiceCall: () => void;
  onVideoCall: () => void;
  requestClose: () => void;
};
const CallMenu = forwardRef<HTMLDivElement, CallMenuProps>(
  ({ requestClose, onVoiceCall, onVideoCall }, ref) => {
    const handleVoice = () => {
      onVoiceCall();
      requestClose();
    };
    const handleVideo = () => {
      onVideoCall();
      requestClose();
    };

    return (
      <Menu ref={ref} style={{ padding: config.space.S200, minWidth: toRem(150) }}>
        <Box direction="Column" gap="200">
          <Text size="L400">Start Call</Text>
          <Box direction="Column" gap="200">
            <Button
              size="300"
              variant="Success"
              fill="Soft"
              outlined
              radii="300"
              before={<Icon size="100" src={Icons.Phone} filled />}
              onClick={handleVoice}
            >
              <Text size="B300">Voice</Text>
            </Button>
            <Button
              size="300"
              variant="Success"
              radii="300"
              before={<Icon size="100" src={Icons.VideoCamera} filled />}
              onClick={handleVideo}
            >
              <Text size="B300">Video</Text>
            </Button>
          </Box>
        </Box>
      </Menu>
    );
  },
);

function CallButton() {
  const room = useRoom();
  const direct = useIsDirectRoom();

  const callEmbed = useCallEmbed();
  const startCall = useCallStart(direct);
  const callStarted = callEmbed && callEmbed.roomId === room.roomId;
  const inAnotherCall = callEmbed && !callStarted;
  const [menuAnchor, setMenuAnchor] = useState<RectCords>();

  const handleOpenMenu: MouseEventHandler<HTMLButtonElement> = (evt) => {
    setMenuAnchor(evt.currentTarget.getBoundingClientRect());
  };

  return (
    <>
      <TooltipProvider
        position="Bottom"
        offset={4}
        tooltip={
          <Tooltip>
            {inAnotherCall ? (
              <Text size="L400">Already in another call — End the current call to join!</Text>
            ) : (
              <Text>Call</Text>
            )}
          </Tooltip>
        }
      >
        {(triggerRef) => (
          <IconButton
            variant="Surface"
            fill="None"
            ref={triggerRef}
            aria-label="Start call"
            onClick={handleOpenMenu}
            onContextMenu={(evt) => {
              evt.preventDefault();
              startCall(room, {
                microphone: true,
                video: true,
                sound: true,
              });
            }}
            disabled={inAnotherCall || callStarted}
            aria-pressed={!!menuAnchor}
          >
            <Icon size="400" src={Icons.VideoCamera} filled={!!menuAnchor} />
          </IconButton>
        )}
      </TooltipProvider>
      <PopOut
        anchor={menuAnchor}
        position="Bottom"
        align="Center"
        content={
          <FocusTrap
            focusTrapOptions={{
              initialFocus: false,
              returnFocusOnDeactivate: false,
              onDeactivate: () => setMenuAnchor(undefined),
              clickOutsideDeactivates: true,
              isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown',
              isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp',
              escapeDeactivates: stopPropagation,
            }}
          >
            <CallMenu
              onVideoCall={() => startCall(room, { microphone: true, video: true, sound: true })}
              onVoiceCall={() => startCall(room, { microphone: true, video: false, sound: true })}
              requestClose={() => setMenuAnchor(undefined)}
            />
          </FocusTrap>
        }
      />
    </>
  );
}

export function RoomViewHeader({ callView }: { callView?: boolean }) {
  const navigate = useNavigate();
  const mx = useMatrixClient();
  const useAuthentication = useMediaAuthentication();
  const screenSize = useScreenSizeContext();
  const room = useRoom();
  const space = useSpaceOptionally();
  const powerLevels = usePowerLevelsContext();
  const creators = useRoomCreators(room);
  const permissions = useRoomPermissions(creators, powerLevels);

  const hasCallPermission = permissions.stateEvent(
    StateEvent.GroupCallMemberPrefix,
    mx.getSafeUserId(),
  );
  const livekitSupported = useLivekitSupport();
  const rtcSupported = webRTCSupported();

  const [menuAnchor, setMenuAnchor] = useState<RectCords>();
  const [pinMenuAnchor, setPinMenuAnchor] = useState<RectCords>();
  const direct = useIsDirectRoom();

  const pinnedEvents = useRoomPinnedEvents(room);
  const encryptionEvent = useStateEvent(room, StateEvent.RoomEncryption);
  const _encryptedRoom = !!encryptionEvent;
  const avatarMxc = useRoomAvatar(room, direct);
  const name = useLocalRoomName(room);
  const topic = useRoomTopic(room);
  const avatarUrl = avatarMxc
    ? (mxcUrlToHttp(mx, avatarMxc, useAuthentication, 96, 96, 'crop') ?? undefined)
    : undefined;

  const [peopleDrawer, setPeopleDrawer] = useSetting(settingsAtom, 'isPeopleDrawer');
  const [galleryOpen, setGalleryOpen] = useAtom(mediaGalleryAtom);
  const [widgetsOpen, setWidgetsOpen] = useAtom(widgetsPanelAtom);
  const pendingKnocks = usePendingKnocks(room);

  const handleSearchClick = () => {
    const searchParams: _SearchPathSearchParams = {
      rooms: room.roomId,
    };
    const path = space
      ? getSpaceSearchPath(getCanonicalAliasOrRoomId(mx, space.roomId))
      : getHomeSearchPath();
    navigate(withSearchParam(path, searchParams));
  };

  const handleOpenMenu: MouseEventHandler<HTMLButtonElement> = (evt) => {
    setMenuAnchor(evt.currentTarget.getBoundingClientRect());
  };

  const handleOpenPinMenu: MouseEventHandler<HTMLButtonElement> = (evt) => {
    setPinMenuAnchor(evt.currentTarget.getBoundingClientRect());
  };

  const openSettings = useOpenRoomSettings();
  const parentSpace = useSpaceOptionally();
  const handleMemberToggle = () => {
    if (callView) {
      openSettings(room.roomId, parentSpace?.roomId, RoomSettingsPage.MembersPage);
      return;
    }
    setPeopleDrawer(!peopleDrawer);
  };

  return (
    <>
      <PageHeader
        className={ContainerColor({ variant: 'Surface' })}
        balance={screenSize === ScreenSize.Mobile}
        aria-label={`${name} room header`}
      >
        <Box grow="Yes" gap="300">
          {screenSize === ScreenSize.Mobile && (
            <BackRouteHandler>
              {(onBack) => (
                <Box shrink="No" alignItems="Center">
                  <IconButton fill="None" onClick={onBack} aria-label="Back">
                    <Icon src={Icons.ArrowLeft} />
                  </IconButton>
                </Box>
              )}
            </BackRouteHandler>
          )}
          <Box grow="Yes" alignItems="Center" gap="300">
            {screenSize !== ScreenSize.Mobile && (
              <Avatar size="300">
                <RoomAvatar
                  roomId={room.roomId}
                  src={avatarUrl}
                  alt={name}
                  renderFallback={() => (
                    <RoomIcon size="200" joinRule={room.getJoinRule()} roomType={room.getType()} />
                  )}
                />
              </Avatar>
            )}
            <Box direction="Column">
              <Box alignItems="Center" gap="200">
                <Text size={topic ? 'H5' : 'H3'} truncate>
                  {name}
                </Text>
                {room.getType() === 'm.server_notice' && (
                  <TooltipProvider
                    position="Bottom"
                    offset={4}
                    tooltip={
                      <Tooltip>
                        <Text>System messages from your homeserver administrator.</Text>
                      </Tooltip>
                    }
                  >
                    {(triggerRef) => (
                      <Chip ref={triggerRef} size="400" variant="Warning" radii="300" outlined>
                        <Text size="T200">Server Notice</Text>
                      </Chip>
                    )}
                  </TooltipProvider>
                )}
              </Box>
              {topic && (
                <UseStateProvider initial={false}>
                  {(viewTopic, setViewTopic) => (
                    <>
                      <Overlay open={viewTopic} backdrop={<OverlayBackdrop />}>
                        <OverlayCenter>
                          <FocusTrap
                            focusTrapOptions={{
                              initialFocus: false,
                              clickOutsideDeactivates: true,
                              onDeactivate: () => setViewTopic(false),
                              escapeDeactivates: stopPropagation,
                            }}
                          >
                            <RoomTopicViewer
                              name={name}
                              topic={topic}
                              requestClose={() => setViewTopic(false)}
                            />
                          </FocusTrap>
                        </OverlayCenter>
                      </Overlay>
                      <Text
                        as="button"
                        type="button"
                        onClick={() => setViewTopic(true)}
                        className={css.HeaderTopic}
                        size="T200"
                        priority="300"
                        truncate
                      >
                        {topic.topic}
                      </Text>
                    </>
                  )}
                </UseStateProvider>
              )}
            </Box>
          </Box>

          <Box shrink="No">
            {
              <TooltipProvider
                position="Bottom"
                offset={4}
                tooltip={
                  <Tooltip>
                    <Text>Search</Text>
                  </Tooltip>
                }
              >
                {(triggerRef) => (
                  <IconButton
                    fill="None"
                    ref={triggerRef}
                    onClick={handleSearchClick}
                    aria-label="Search"
                  >
                    <Icon size="400" src={Icons.Search} />
                  </IconButton>
                )}
              </TooltipProvider>
            }
            <TooltipProvider
              position="Bottom"
              offset={4}
              tooltip={
                <Tooltip>
                  <Text>Pinned Messages</Text>
                </Tooltip>
              }
            >
              {(triggerRef) => (
                <IconButton
                  fill="None"
                  style={{ position: 'relative' }}
                  onClick={handleOpenPinMenu}
                  ref={triggerRef}
                  aria-label="Pinned messages"
                  aria-pressed={!!pinMenuAnchor}
                >
                  {pinnedEvents.length > 0 && (
                    <Badge
                      style={{
                        position: 'absolute',
                        left: toRem(3),
                        top: toRem(3),
                      }}
                      variant="Secondary"
                      size="400"
                      fill="Solid"
                      radii="Pill"
                    >
                      <Text as="span" size="L400">
                        {pinnedEvents.length}
                      </Text>
                    </Badge>
                  )}
                  <Icon size="400" src={Icons.Pin} filled={!!pinMenuAnchor} />
                </IconButton>
              )}
            </TooltipProvider>
            <PopOut
              anchor={pinMenuAnchor}
              position="Bottom"
              content={
                <FocusTrap
                  focusTrapOptions={{
                    initialFocus: false,
                    returnFocusOnDeactivate: false,
                    onDeactivate: () => setPinMenuAnchor(undefined),
                    clickOutsideDeactivates: true,
                    isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown',
                    isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp',
                    escapeDeactivates: stopPropagation,
                  }}
                >
                  <RoomPinMenu room={room} requestClose={() => setPinMenuAnchor(undefined)} />
                </FocusTrap>
              }
            />
            {!room.isCallRoom() &&
              livekitSupported &&
              rtcSupported &&
              hasCallPermission &&
              (direct ||
                (room.getJoinRule() === 'invite' &&
                  getStateEvents(room, StateEvent.SpaceParent).length === 0)) && <CallButton />}
            {screenSize === ScreenSize.Desktop && (
              <TooltipProvider
                position="Bottom"
                offset={4}
                tooltip={
                  <Tooltip>
                    <Text>{galleryOpen ? 'Hide Gallery' : 'Media Gallery'}</Text>
                  </Tooltip>
                }
              >
                {(triggerRef) => (
                  <IconButton
                    fill="None"
                    ref={triggerRef}
                    onClick={() => setGalleryOpen(!galleryOpen)}
                    aria-label="Toggle media gallery"
                    aria-pressed={galleryOpen}
                  >
                    <Icon size="400" src={Icons.Photo} filled={galleryOpen} />
                  </IconButton>
                )}
              </TooltipProvider>
            )}
            {screenSize === ScreenSize.Desktop && (
              <TooltipProvider
                position="Bottom"
                offset={4}
                tooltip={
                  <Tooltip>
                    <Text>{widgetsOpen ? 'Hide Widgets' : 'Widgets'}</Text>
                  </Tooltip>
                }
              >
                {(triggerRef) => (
                  <IconButton
                    fill="None"
                    ref={triggerRef}
                    onClick={() => setWidgetsOpen(!widgetsOpen)}
                    aria-label="Toggle widgets"
                    aria-pressed={widgetsOpen}
                  >
                    <Icon size="400" src={Icons.Category} filled={widgetsOpen} />
                  </IconButton>
                )}
              </TooltipProvider>
            )}
            {screenSize === ScreenSize.Desktop && (
              <TooltipProvider
                position="Bottom"
                offset={4}
                tooltip={
                  <Tooltip>
                    {callView ? (
                      <Text>Members</Text>
                    ) : (
                      <Text>{peopleDrawer ? 'Hide Members' : 'Show Members'}</Text>
                    )}
                  </Tooltip>
                }
              >
                {(triggerRef) => (
                  <IconButton
                    fill="None"
                    ref={triggerRef}
                    style={{ position: 'relative' }}
                    onClick={handleMemberToggle}
                    aria-label={
                      pendingKnocks.length > 0
                        ? `Toggle member list, ${pendingKnocks.length} pending join request${pendingKnocks.length > 1 ? 's' : ''}`
                        : 'Toggle member list'
                    }
                  >
                    {pendingKnocks.length > 0 && (
                      <Badge
                        aria-hidden
                        variant="Warning"
                        fill="Solid"
                        radii="Pill"
                        size="400"
                        style={{
                          position: 'absolute',
                          right: toRem(3),
                          top: toRem(3),
                          pointerEvents: 'none',
                        }}
                      >
                        <Text as="span" size="L400">
                          {pendingKnocks.length > 9 ? '9+' : pendingKnocks.length}
                        </Text>
                      </Badge>
                    )}
                    <Icon size="400" src={Icons.User} />
                  </IconButton>
                )}
              </TooltipProvider>
            )}

            <TooltipProvider
              position="Bottom"
              align="End"
              offset={4}
              tooltip={
                <Tooltip>
                  <Text>More Options</Text>
                </Tooltip>
              }
            >
              {(triggerRef) => (
                <IconButton
                  fill="None"
                  onClick={handleOpenMenu}
                  ref={triggerRef}
                  aria-label="More options"
                  aria-expanded={!!menuAnchor}
                  aria-haspopup="menu"
                >
                  <Icon size="400" src={Icons.VerticalDots} filled={!!menuAnchor} />
                </IconButton>
              )}
            </TooltipProvider>
            <PopOut
              anchor={menuAnchor}
              position="Bottom"
              align="End"
              content={
                <FocusTrap
                  focusTrapOptions={{
                    initialFocus: false,
                    returnFocusOnDeactivate: false,
                    onDeactivate: () => setMenuAnchor(undefined),
                    clickOutsideDeactivates: true,
                    isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown',
                    isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp',
                    escapeDeactivates: stopPropagation,
                  }}
                >
                  <RoomMenu
                    room={room}
                    requestClose={() => setMenuAnchor(undefined)}
                    galleryOpen={galleryOpen}
                    onToggleGallery={() => setGalleryOpen((v: boolean) => !v)}
                  />
                </FocusTrap>
              }
            />
          </Box>
        </Box>
      </PageHeader>
    </>
  );
}
