// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { useRef } from 'react';
import { smartDominantSpeakerParticipants } from '../../../gallery';
const DEFAULT_MAX_OVERFLOW_GALLERY_DOMINANT_SPEAKERS = 6;
const DEFAULT_MAX_VIDEO_SREAMS = 4;
/**
 * @private
 */
export const MAX_GRID_PARTICIPANTS_NOT_LARGE_GALLERY = 9;
const getOrganizedParticipants = (props) => {
    const { remoteParticipants = [], dominantSpeakers = [], maxGridParticipants = DEFAULT_MAX_VIDEO_SREAMS, maxOverflowGalleryDominantSpeakers = DEFAULT_MAX_OVERFLOW_GALLERY_DOMINANT_SPEAKERS, layout, previousGridParticipants = [], previousOverflowParticipants = [] } = props;
    const callingParticipants = remoteParticipants.filter(p => p.state === 'Connecting' || p.state === 'Ringing');
    const callingParticipantsSet = new Set(callingParticipants.map(p => p.userId));
    const connectedParticipants = remoteParticipants.filter(p => !callingParticipantsSet.has(p.userId));
    const remoteParticipantsOrdered = putVideoParticipantsFirst(connectedParticipants);
    const videoParticipants = remoteParticipants.filter(p => { var _a; return (_a = p.videoStream) === null || _a === void 0 ? void 0 : _a.isAvailable; });
    const participantsForGrid = layout === 'floatingLocalVideo' && videoParticipants.length > 0 ? videoParticipants : remoteParticipantsOrdered;
    let newGridParticipants = smartDominantSpeakerParticipants({
        participants: participantsForGrid,
        dominantSpeakers,
        currentParticipants: previousGridParticipants,
        maxDominantSpeakers: maxGridParticipants
    }).slice(0, maxGridParticipants);
    if (layout === 'speaker') {
        if (dominantSpeakers === null || dominantSpeakers === void 0 ? void 0 : dominantSpeakers[0]) {
            newGridParticipants = newGridParticipants.filter(p => p.userId === dominantSpeakers[0]);
        }
        else {
            newGridParticipants = newGridParticipants.slice(1);
        }
    }
    const gridParticipantSet = new Set(newGridParticipants.map(p => p.userId));
    const newOverflowGalleryParticipants = smartDominantSpeakerParticipants({
        participants: remoteParticipantsOrdered.filter(p => !gridParticipantSet.has(p.userId)),
        dominantSpeakers: dominantSpeakers,
        currentParticipants: previousOverflowParticipants,
        maxDominantSpeakers: maxOverflowGalleryDominantSpeakers
    });
    let gridParticipants = newGridParticipants;
    let overflowGalleryParticipants = newOverflowGalleryParticipants;
    // Add the participants being called into the call.
    // If there are already overflow participants, add these to the array of overflow participants
    // Otherwise, add the maximum number to the main grid, then put the rest in the overflow
    if (overflowGalleryParticipants.length === 0) {
        const numberOfCallingParticipantsInGrid = maxGridParticipants - gridParticipants.length;
        const gridCallingParticipants = callingParticipants.slice(0, numberOfCallingParticipantsInGrid);
        const overflowGalleryCallingParticipants = callingParticipants.slice(numberOfCallingParticipantsInGrid);
        gridParticipants = gridParticipants.concat(gridCallingParticipants);
        overflowGalleryParticipants = overflowGalleryCallingParticipants;
    }
    else {
        overflowGalleryParticipants = overflowGalleryParticipants.concat(callingParticipants);
    }
    return {
        gridParticipants,
        overflowGalleryParticipants
    };
};
/**
 * Hook to determine which participants should be in grid and overflow gallery and their order respectively
 * @private
 */
export const useOrganizedParticipants = (props) => {
    var _a, _b;
    const spotlightedParticipantUserIds = (_a = props.spotlightedParticipantUserIds) !== null && _a !== void 0 ? _a : [];
    const pinnedParticipantUserIds = (_b = props.pinnedParticipantUserIds) !== null && _b !== void 0 ? _b : [];
    // Focussed participants are the participants that are either spotlighted or pinned. Ordered by spotlighted first and then pinned.
    // A set is used to dedupe participants.
    const focusedParticipantUserIdSet = new Set(spotlightedParticipantUserIds.concat(pinnedParticipantUserIds));
    const focusedParticipants = [...focusedParticipantUserIdSet].map(userId => props.remoteParticipants.find(p => p.userId === userId)).filter(p => p !== undefined);
    // Unfocused participants are the rest of the participants
    const unfocusedParticipants = props.remoteParticipants.filter(p => !focusedParticipantUserIdSet.has(p.userId));
    const currentGridParticipants = useRef([]);
    const currentOverflowGalleryParticipants = useRef([]);
    const organizedParticipantsArgs = Object.assign(Object.assign({}, props), { 
        // if there are focused participants then leave no room in the grid by setting maxGridParticipants to 0
        maxGridParticipants: focusedParticipants.length > 0 || props.isScreenShareActive ? 0 : props.maxGridParticipants, remoteParticipants: unfocusedParticipants, previousGridParticipants: currentGridParticipants.current, previousOverflowParticipants: currentOverflowGalleryParticipants.current });
    const organizedParticipants = getOrganizedParticipants(organizedParticipantsArgs);
    currentGridParticipants.current = organizedParticipants.gridParticipants;
    currentOverflowGalleryParticipants.current = organizedParticipants.overflowGalleryParticipants;
    return focusedParticipants.length > 0 ? {
        gridParticipants: props.isScreenShareActive ? [] : focusedParticipants,
        overflowGalleryParticipants: props.isScreenShareActive ? focusedParticipants.concat(organizedParticipants.overflowGalleryParticipants) : organizedParticipants.overflowGalleryParticipants
    } : organizedParticipants;
};
const putVideoParticipantsFirst = (remoteParticipants) => {
    const videoParticipants = [];
    const audioParticipants = [];
    remoteParticipants.forEach(p => {
        var _a;
        if ((_a = p.videoStream) === null || _a === void 0 ? void 0 : _a.isAvailable) {
            videoParticipants.push(p);
        }
        else {
            audioParticipants.push(p);
        }
    });
    const remoteParticipantSortedByVideo = videoParticipants.concat(audioParticipants);
    return remoteParticipantSortedByVideo;
};
/**
 * @private
 */
export const renderTiles = (gridParticipants, onRenderRemoteParticipant, maxRemoteVideoStreams, indexesToRender, overflowGalleryParticipants, dominantSpeakers) => {
    const _dominantSpeakers = dominantSpeakers !== null && dominantSpeakers !== void 0 ? dominantSpeakers : [];
    let streamsLeftToRender = maxRemoteVideoStreams;
    // Render the grid participants
    const participantWithStreamsToRenderInGrid = gridParticipants.filter(p => { var _a; return (_a = p === null || p === void 0 ? void 0 : p.videoStream) === null || _a === void 0 ? void 0 : _a.isAvailable; });
    const dominantSpeakerWithStreamsToRenderInGrid = _dominantSpeakers.filter(userId => participantWithStreamsToRenderInGrid.find(p => (p === null || p === void 0 ? void 0 : p.userId) === userId)).slice(0, streamsLeftToRender);
    streamsLeftToRender = streamsLeftToRender - dominantSpeakerWithStreamsToRenderInGrid.length;
    const gridTiles = gridParticipants.map(p => {
        var _a;
        return onRenderRemoteParticipant(p, dominantSpeakerWithStreamsToRenderInGrid.includes(p.userId) || ((_a = p.videoStream) === null || _a === void 0 ? void 0 : _a.isAvailable) && streamsLeftToRender-- > 0);
    });
    // Render the overflow participants
    const participantWithStreamsToRenderInOverflow = indexesToRender.map(i => {
        return overflowGalleryParticipants.at(i);
    }).filter(p => { var _a; return (_a = p === null || p === void 0 ? void 0 : p.videoStream) === null || _a === void 0 ? void 0 : _a.isAvailable; });
    const dominantSpeakerWithStreamsToRenderInOverflow = _dominantSpeakers.filter(userId => participantWithStreamsToRenderInOverflow.find(p => (p === null || p === void 0 ? void 0 : p.userId) === userId)).slice(0, streamsLeftToRender);
    streamsLeftToRender = streamsLeftToRender - dominantSpeakerWithStreamsToRenderInOverflow.length;
    const overflowGalleryTiles = overflowGalleryParticipants.map(p => {
        var _a;
        return onRenderRemoteParticipant(p, dominantSpeakerWithStreamsToRenderInOverflow.includes(p.userId) || ((_a = p.videoStream) === null || _a === void 0 ? void 0 : _a.isAvailable) && streamsLeftToRender-- > 0);
    });
    return {
        gridTiles,
        overflowGalleryTiles
    };
};
/**
 * @private
 */
export const getEmojiResource = (reactionName, reactionResources) => {
    var _a, _b, _c, _d, _e;
    switch (reactionName) {
        case 'like':
            return (_a = reactionResources.likeReaction) === null || _a === void 0 ? void 0 : _a.url;
        case 'heart':
            return (_b = reactionResources.heartReaction) === null || _b === void 0 ? void 0 : _b.url;
        case 'laugh':
            return (_c = reactionResources.laughReaction) === null || _c === void 0 ? void 0 : _c.url;
        case 'applause':
            return (_d = reactionResources.applauseReaction) === null || _d === void 0 ? void 0 : _d.url;
        case 'surprised':
            return (_e = reactionResources.surprisedReaction) === null || _e === void 0 ? void 0 : _e.url;
    }
    return undefined;
};
/**
 * @private
 */
export const getEmojiFrameCount = (reactionName, reactionResources) => {
    var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
    switch (reactionName) {
        case 'like':
            return (_b = (_a = reactionResources.likeReaction) === null || _a === void 0 ? void 0 : _a.frameCount) !== null && _b !== void 0 ? _b : 0;
        case 'heart':
            return (_d = (_c = reactionResources.heartReaction) === null || _c === void 0 ? void 0 : _c.frameCount) !== null && _d !== void 0 ? _d : 0;
        case 'laugh':
            return (_f = (_e = reactionResources.laughReaction) === null || _e === void 0 ? void 0 : _e.frameCount) !== null && _f !== void 0 ? _f : 0;
        case 'applause':
            return (_h = (_g = reactionResources.applauseReaction) === null || _g === void 0 ? void 0 : _g.frameCount) !== null && _h !== void 0 ? _h : 0;
        case 'surprised':
            return (_k = (_j = reactionResources.surprisedReaction) === null || _j === void 0 ? void 0 : _j.frameCount) !== null && _k !== void 0 ? _k : 0;
        default:
            return 0;
    }
};
//# sourceMappingURL=videoGalleryLayoutUtils.js.map