// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { Layer, Stack } from '@fluentui/react';
import React, { useMemo } from 'react';
import { useCallback } from 'react';
import { _DrawerMenu } from './Drawer';
import { StreamMedia } from './StreamMedia';
import { drawerMenuWrapperStyles, remoteVideoTileWrapperStyle } from './VideoGallery/styles/RemoteVideoTile.styles';
import { useRemoteVideoStreamLifecycleMaintainer } from './VideoGallery/useVideoStreamLifecycleMaintainer';
import { useVideoTileContextualMenuProps } from './VideoGallery/useVideoTileContextualMenuProps';
import { VideoTile } from './VideoTile';
import { _formatString } from "../../../acs-ui-common/src";
import { MeetingReactionOverlay } from './MeetingReactionOverlay';
/**
 * A memoized version of VideoTile for rendering remote participants. React.memo is used for a performance
 * boost by memoizing the same rendered component to avoid rerendering a VideoTile when its position in the
 * array changes causing a rerender in the parent component. https://reactjs.org/docs/react-api.html#reactmemo
 *
 * @internal
 */
export const _RemoteVideoTile = React.memo((props) => {
    var _a, _b;
    const { isAvailable, isReceiving = true, 
    // default to true to prevent any breaking change
    isScreenSharingOn, onCreateRemoteStreamView, onDisposeRemoteStreamView, remoteVideoViewOptions, renderElement, userId, onRenderAvatar, showMuteIndicator, remoteParticipant, participantState, menuKind, isPinned, onPinParticipant, onUnpinParticipant, spotlightedParticipantUserIds, isSpotlighted, onStartSpotlight, onStopSpotlight, maxParticipantsToSpotlight, onMuteParticipant, onUpdateScalingMode, disablePinMenuItem, toggleAnnouncerString, strings, reactionResources, streamId, onForbidAudio, onPermitAudio, onForbidVideo, onPermitVideo } = props;
    const remoteVideoStreamProps = useMemo(() => ({
        isMirrored: remoteVideoViewOptions === null || remoteVideoViewOptions === void 0 ? void 0 : remoteVideoViewOptions.isMirrored,
        isScreenSharingOn,
        isStreamAvailable: isAvailable,
        isStreamReceiving: isReceiving,
        onCreateRemoteStreamView,
        onDisposeRemoteStreamView,
        remoteParticipantId: userId,
        renderElementExists: !!renderElement,
        scalingMode: remoteVideoViewOptions === null || remoteVideoViewOptions === void 0 ? void 0 : remoteVideoViewOptions.scalingMode,
        streamId,
        isVideoPermitted: remoteParticipant.mediaAccess ? remoteParticipant.mediaAccess.isVideoPermitted : true
    }), [isAvailable, isReceiving, isScreenSharingOn, onCreateRemoteStreamView, onDisposeRemoteStreamView, remoteVideoViewOptions === null || remoteVideoViewOptions === void 0 ? void 0 : remoteVideoViewOptions.isMirrored, remoteVideoViewOptions === null || remoteVideoViewOptions === void 0 ? void 0 : remoteVideoViewOptions.scalingMode, renderElement, userId, streamId, remoteParticipant.mediaAccess]);
    // Handle creating, destroying and updating the video stream as necessary
    const createVideoStreamResult = useRemoteVideoStreamLifecycleMaintainer(remoteVideoStreamProps);
    const contextualMenuProps = useVideoTileContextualMenuProps({
        participant: remoteParticipant,
        view: createVideoStreamResult === null || createVideoStreamResult === void 0 ? void 0 : createVideoStreamResult.view,
        strings: Object.assign({}, props.strings),
        isPinned,
        onPinParticipant,
        onUnpinParticipant,
        onUpdateScalingMode,
        disablePinMenuItem,
        toggleAnnouncerString,
        spotlightedParticipantUserIds,
        isSpotlighted,
        onStartSpotlight,
        onStopSpotlight,
        maxParticipantsToSpotlight,
        onMuteParticipant,
        onForbidAudio,
        onPermitAudio,
        onForbidVideo,
        onPermitVideo
    });
    const videoTileContextualMenuProps = useMemo(() => {
        if (menuKind !== 'contextual' || !contextualMenuProps) {
            return {};
        }
        return {
            contextualMenu: contextualMenuProps
        };
    }, [contextualMenuProps, menuKind]);
    const showLoadingIndicator = isAvailable && isReceiving === false && participantState !== 'Disconnected';
    const isReconnecting = participantState === 'Reconnecting';
    const [drawerMenuItemProps, setDrawerMenuItemProps] = React.useState([]);
    const renderVideoStreamElement = useMemo(() => {
        // Checking if renderElement is well defined or not as calling SDK has a number of video streams limitation which
        // implies that, after their threshold, all streams have no child (blank video)
        if ((!renderElement || !renderElement.childElementCount) && !isReconnecting) {
            // Returning `undefined` results in the placeholder with avatar being shown
            return undefined;
        }
        return React.createElement(StreamMedia, { videoStreamElement: renderElement !== null && renderElement !== void 0 ? renderElement : null, loadingState: showLoadingIndicator ? 'loading' : isReconnecting ? 'reconnecting' : 'none' });
    }, [isReconnecting, renderElement, showLoadingIndicator]);
    const onKeyDown = useCallback((e) => {
        if (e.key === 'Enter') {
            setDrawerMenuItemProps(convertContextualMenuItemsToDrawerMenuItemProps(contextualMenuProps, () => setDrawerMenuItemProps([])));
        }
    }, [setDrawerMenuItemProps, contextualMenuProps]);
    const attendeeRoleString = (_a = props.strings) === null || _a === void 0 ? void 0 : _a.attendeeRole;
    const formatDisplayName = (displayName, role) => {
        if (displayName && role) {
            return _formatString(displayName, {
                AttendeeRole: role
            });
        }
        return displayName;
    };
    const displayName = formatDisplayName(remoteParticipant.displayName ? remoteParticipant.displayName : strings.displayNamePlaceholder, attendeeRoleString);
    const formatInitialsName = () => {
        if (remoteParticipant.displayName && attendeeRoleString) {
            return _formatString(remoteParticipant.displayName, {
                AttendeeRole: attendeeRoleString
            });
        }
        return remoteParticipant.displayName;
    };
    const reactionOverlay = reactionResources && React.createElement(MeetingReactionOverlay, { overlayMode: "grid-tiles", reaction: remoteParticipant.reaction, reactionResources: reactionResources });
    return React.createElement(Stack, { tabIndex: menuKind === 'drawer' ? 0 : undefined, onKeyDown: menuKind === 'drawer' ? onKeyDown : undefined, style: remoteVideoTileWrapperStyle },
        React.createElement(VideoTile, Object.assign({ key: userId, userId: userId, initialsName: (_b = formatInitialsName()) !== null && _b !== void 0 ? _b : '', renderElement: renderVideoStreamElement, displayName: displayName, onRenderPlaceholder: onRenderAvatar, isMuted: remoteParticipant.isMuted, raisedHand: remoteParticipant.raisedHand, isSpeaking: remoteParticipant.isSpeaking, showMuteIndicator: showMuteIndicator, personaMinSize: props.personaMinSize, showLabel: props.showLabel, alwaysShowLabelBackground: props.alwaysShowLabelBackground, participantState: participantState }, videoTileContextualMenuProps, { isPinned: props.isPinned, onLongTouch: props.onLongTouch ? props.onLongTouch : () => setDrawerMenuItemProps(convertContextualMenuItemsToDrawerMenuItemProps(contextualMenuProps, () => setDrawerMenuItemProps([]))), isSpotlighted: isSpotlighted, overlay: reactionOverlay, mediaAccess: remoteParticipant.mediaAccess })),
        drawerMenuItemProps.length > 0 && React.createElement(Layer, { hostId: props.drawerMenuHostId },
            React.createElement(Stack, { styles: drawerMenuWrapperStyles },
                React.createElement(_DrawerMenu, { onLightDismiss: () => setDrawerMenuItemProps([]), items: drawerMenuItemProps, heading: displayName }))));
});
const convertContextualMenuItemsToDrawerMenuItemProps = (contextualMenuProps, onLightDismiss) => {
    if (!contextualMenuProps) {
        return [];
    }
    return contextualMenuProps.items.map(item => {
        return {
            itemKey: item.key,
            text: item.text,
            iconProps: item.iconProps,
            disabled: item.disabled,
            onItemClick: () => {
                var _a;
                (_a = item.onClick) === null || _a === void 0 ? void 0 : _a.call(item);
                onLightDismiss === null || onLightDismiss === void 0 ? void 0 : onLightDismiss();
            }
        };
    });
};
//# sourceMappingURL=RemoteVideoTile.js.map