// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import React, { useMemo, useState, memo, useEffect } from 'react';
import { moveAnimationStyles, spriteAnimationStyles } from './styles/ReactionOverlay.style';
import { REACTION_NUMBER_OF_ANIMATION_FRAMES } from './VideoGallery/utils/reactionUtils';
import { Icon, mergeStyles, Stack, Text } from '@fluentui/react';
import { getEmojiResource } from './VideoGallery/utils/videoGalleryLayoutUtils';
import { useLocale } from '../localization';
import { calculateScaledSize, getTogetherModeParticipantOverlayStyle, participantStatusTransitionStyle, REACTION_MAX_TRAVEL_HEIGHT, REACTION_TRAVEL_HEIGHT, setTogetherModeSeatPositionStyle, togetherModeIconStyle, togetherModeParticipantDisplayName, togetherModeParticipantEmojiSpriteStyle, togetherModeParticipantStatusContainer } from './styles/TogetherMode.styles';
import { useTheme } from '../theming';
import { RaisedHandIcon } from './assets/RaisedHandIcon';
/**
 * TogetherModeOverlay component renders an empty JSX element.
 *
 * @returns {JSX.Element} An empty JSX element.
 */
export const TogetherModeOverlay = memo((props) => {
    const locale = useLocale();
    const theme = useTheme();
    const callingPalette = theme.callingPalette;
    const { emojiSize, reactionResources, remoteParticipants, localParticipant, togetherModeSeatPositions } = props;
    const [togetherModeParticipantStatus, setTogetherModeParticipantStatus] = useState({});
    const [hoveredParticipantID, setHoveredParticipantID] = useState('');
    /*
     * The useMemo hook is used to calculate the participant status for the Together Mode overlay.
     * It updates the togetherModeParticipantStatus state when there's a change in the remoteParticipants, localParticipant,
     * raisedHand, spotlight, isMuted, displayName, or hoveredParticipantID.
     */
    const updatedParticipantStatus = useMemo(() => {
        const allParticipants = [...remoteParticipants, localParticipant];
        const participantsWithVideoAvailable = allParticipants.filter(p => { var _a; return ((_a = p.videoStream) === null || _a === void 0 ? void 0 : _a.isAvailable) && togetherModeSeatPositions[p.userId]; });
        const updatedSignals = {};
        for (const p of participantsWithVideoAvailable) {
            const { userId, reaction, raisedHand, spotlight, isMuted, displayName } = p;
            const seatingPosition = togetherModeSeatPositions[userId];
            if (seatingPosition) {
                updatedSignals[userId] = {
                    id: userId,
                    reaction: reactionResources && reaction,
                    isHandRaised: !!raisedHand,
                    isSpotlighted: !!spotlight,
                    isMuted,
                    displayName: displayName || locale.strings.videoGallery.displayNamePlaceholder,
                    showDisplayName: !!(spotlight || raisedHand || hoveredParticipantID === userId),
                    scaledSize: calculateScaledSize(seatingPosition.width, seatingPosition.height),
                    seatPositionStyle: setTogetherModeSeatPositionStyle(seatingPosition)
                };
            }
        }
        // This is used to remove the participants bounding box from the DOM when they are no longer in the stream
        const participantsNotInTogetherModeStream = Object.keys(togetherModeParticipantStatus).filter(id => !updatedSignals[id]);
        const newSignals = Object.assign(Object.assign({}, togetherModeParticipantStatus), updatedSignals);
        participantsNotInTogetherModeStream.forEach(id => {
            delete newSignals[id];
        });
        const hasSignalingChange = Object.keys(newSignals).some(key => JSON.stringify(newSignals[key]) !== JSON.stringify(togetherModeParticipantStatus[key]));
        const updateTogetherModeParticipantStatusState = hasSignalingChange || Object.keys(newSignals).length !== Object.keys(togetherModeParticipantStatus).length;
        return updateTogetherModeParticipantStatusState ? newSignals : togetherModeParticipantStatus;
    }, [remoteParticipants, localParticipant, togetherModeParticipantStatus, togetherModeSeatPositions, reactionResources, locale.strings.videoGallery.displayNamePlaceholder, hoveredParticipantID]);
    useEffect(() => {
        if (hoveredParticipantID && !updatedParticipantStatus[hoveredParticipantID]) {
            setHoveredParticipantID('');
        }
        setTogetherModeParticipantStatus(updatedParticipantStatus);
    }, [hoveredParticipantID, updatedParticipantStatus]);
    return React.createElement("div", { style: {
            position: 'absolute',
            width: '100%',
            height: '100%',
            overflow: 'hidden'
        } }, Object.values(togetherModeParticipantStatus).map(participantStatus => {
        var _a, _b;
        return participantStatus.id && React.createElement("div", { key: participantStatus.id, "data-ui-id": `together-mode-participant-${participantStatus.id}`, style: Object.assign({}, getTogetherModeParticipantOverlayStyle(participantStatus.seatPositionStyle)), onMouseEnter: () => setHoveredParticipantID(participantStatus.id), onMouseLeave: () => setHoveredParticipantID('') },
            React.createElement("div", null,
                participantStatus.showDisplayName && React.createElement("div", { style: Object.assign({}, participantStatusTransitionStyle) },
                    React.createElement("div", { style: Object.assign({}, togetherModeParticipantStatusContainer(callingPalette.videoTileLabelBackgroundLight, theme.effects.roundedCorner4)) },
                        participantStatus.isHandRaised && React.createElement(RaisedHandIcon, null),
                        participantStatus.showDisplayName && React.createElement(Text, { style: Object.assign({}, togetherModeParticipantDisplayName(hoveredParticipantID === participantStatus.id, parseFloat(participantStatus.seatPositionStyle.seatPosition.width), participantStatus.displayName ? theme.palette.neutralSecondary : 'inherit')) }, participantStatus.displayName),
                        participantStatus.isMuted && React.createElement(Stack, { className: mergeStyles(togetherModeIconStyle) },
                            React.createElement(Icon, { iconName: "VideoTileMicOff" })),
                        participantStatus.isSpotlighted && React.createElement(Stack, { className: mergeStyles(togetherModeIconStyle) },
                            React.createElement(Icon, { iconName: "VideoTileSpotlighted" })))),
                ((_a = participantStatus.reaction) === null || _a === void 0 ? void 0 : _a.reactionType) &&
                    // First div - Section that fixes the travel height and applies the movement animation
                    // Second div - Responsible for ensuring the sprite emoji is always centered in the participant seat position
                    // Third div - Play Animation as the other animation applies on the base play animation for the sprite
                    React.createElement("div", { style: moveAnimationStyles(parseFloat(participantStatus.seatPositionStyle.seatPosition.height) * REACTION_MAX_TRAVEL_HEIGHT, parseFloat(participantStatus.seatPositionStyle.seatPosition.height) * REACTION_TRAVEL_HEIGHT) },
                        React.createElement("div", { "data-ui-id": `together-mode-participant-reaction-${participantStatus.id}`, style: Object.assign({}, togetherModeParticipantEmojiSpriteStyle(emojiSize, participantStatus.scaledSize || 1, participantStatus.seatPositionStyle.seatPosition.width)) },
                            React.createElement("div", { style: spriteAnimationStyles(REACTION_NUMBER_OF_ANIMATION_FRAMES, participantStatus.scaledSize || 1, (_b = (participantStatus.reaction && getEmojiResource(participantStatus === null || participantStatus === void 0 ? void 0 : participantStatus.reaction.reactionType, reactionResources))) !== null && _b !== void 0 ? _b : '') })))));
    }));
});
//# sourceMappingURL=TogetherModeOverlay.js.map