// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { toFlatCommunicationIdentifier, _formatString } from "../../../../../acs-ui-common/src";
import { useMemo, useRef, useState } from 'react';
import { useLocale } from '../../localization';
import { useSelector } from '../hooks/useSelector';
import { getRemoteParticipantsConnectedSelector } from '../selectors/mediaGallerySelector';
import { isMicrosoftTeamsAppIdentifier, isPhoneNumberIdentifier } from '@azure/communication-common';
/**
 * sets the announcement string whenever a Participant comes or goes from a call to be
 * used by the system narrator.
 *
 * @returns string to be used by the narrator and Announcer component
 *
 * @internal
 */
export const useParticipantChangedAnnouncement = () => {
    const locale = useLocale().strings.call;
    const strings = useMemo(() => {
        return {
            participantJoinedNoticeString: locale.participantJoinedNoticeString,
            twoParticipantJoinedNoticeString: locale.twoParticipantJoinedNoticeString,
            threeParticipantJoinedNoticeString: locale.threeParticipantJoinedNoticeString,
            participantLeftNoticeString: locale.participantLeftNoticeString,
            twoParticipantLeftNoticeString: locale.twoParticipantLeftNoticeString,
            threeParticipantLeftNoticeString: locale.threeParticipantLeftNoticeString,
            unnamedParticipantString: locale.unnamedParticipantString,
            manyParticipantsJoined: locale.manyParticipantsJoined,
            manyParticipantsLeft: locale.manyParticipantsLeft,
            manyUnnamedParticipantsJoined: locale.manyUnnamedParticipantsJoined,
            manyUnnamedParticipantsLeft: locale.manyUnnamedParticipantsLeft
        };
    }, [locale]);
    const [announcerString, setAnnouncerString] = useState('');
    const currentParticipants = useSelector(getRemoteParticipantsConnectedSelector);
    /**
     * We want to use a useRef here since we want to not fire this hook based on the previous participants
     * this allows this value to be used in the hook without being in the dependency array.
     *
     * Note: By definition if this hook is used in another component it is not pure anymore.
     */
    const previousParticipants = useRef(currentParticipants);
    const resetAnnoucement = (string) => {
        setAnnouncerString(string);
    };
    useMemo(() => {
        const currentIds = currentParticipants.map(p => toFlatCommunicationIdentifier(p.identifier));
        const previousIds = previousParticipants.current.map(p => toFlatCommunicationIdentifier(p.identifier));
        const whoJoined = currentParticipants.filter(p => !previousIds.includes(toFlatCommunicationIdentifier(p.identifier)));
        const whoLeft = previousParticipants.current.filter(p => !currentIds.includes(toFlatCommunicationIdentifier(p.identifier)));
        if (whoJoined.length > 0) {
            resetAnnoucement(createAnnouncementString('joined', whoJoined, strings));
        }
        if (whoLeft.length > 0) {
            resetAnnoucement(createAnnouncementString('left', whoLeft, strings));
        }
        // Update cached value at the end.
        previousParticipants.current = currentParticipants;
    }, [currentParticipants, strings]);
    return announcerString;
};
/**
 * Generates the announcement string for when a participant joins or leaves a call.
 */
export const createAnnouncementString = (direction, participants, strings) => {
    var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
    /**
     * If there are no participants return empty string.
     */
    if (participants.length === 0) {
        return '';
    }
    /**
     * Filter participants into two arrays to put all the unnamed participants at the back of the
     * names being announced.
     */
    const unnamedParticipants = participants.filter(p => !p.displayName);
    const namedParicipants = participants.filter(p => p.displayName);
    const sortedParticipants = namedParicipants.concat(unnamedParticipants);
    /**
     * if there are only unnamed participants present in the array announce a special unnamed participants
     * only string.
     */
    if (sortedParticipants.filter(p => p.displayName).length === 0 && sortedParticipants.length > 1) {
        return _formatString(direction === 'joined' ? strings.manyUnnamedParticipantsJoined : strings.manyUnnamedParticipantsLeft, {
            numOfParticipants: (sortedParticipants.length - 1).toString()
        });
    }
    switch (sortedParticipants.length) {
        case 1:
            return _formatString(direction === 'joined' ? strings.participantJoinedNoticeString : strings.participantLeftNoticeString, {
                displayName: (_b = (_a = sortedParticipants[0]) === null || _a === void 0 ? void 0 : _a.displayName) !== null && _b !== void 0 ? _b : strings.unnamedParticipantString
            });
        case 2:
            return _formatString(direction === 'joined' ? strings.twoParticipantJoinedNoticeString : strings.twoParticipantLeftNoticeString, {
                displayName1: (_d = (_c = sortedParticipants[0]) === null || _c === void 0 ? void 0 : _c.displayName) !== null && _d !== void 0 ? _d : strings.unnamedParticipantString,
                displayName2: (_f = (_e = sortedParticipants[1]) === null || _e === void 0 ? void 0 : _e.displayName) !== null && _f !== void 0 ? _f : strings.unnamedParticipantString
            });
        case 3:
            return _formatString(direction === 'joined' ? strings.threeParticipantJoinedNoticeString : strings.threeParticipantLeftNoticeString, {
                displayName1: (_h = (_g = sortedParticipants[0]) === null || _g === void 0 ? void 0 : _g.displayName) !== null && _h !== void 0 ? _h : strings.unnamedParticipantString,
                displayName2: (_k = (_j = sortedParticipants[1]) === null || _j === void 0 ? void 0 : _j.displayName) !== null && _k !== void 0 ? _k : strings.unnamedParticipantString,
                displayName3: (_m = (_l = sortedParticipants[2]) === null || _l === void 0 ? void 0 : _l.displayName) !== null && _m !== void 0 ? _m : strings.unnamedParticipantString
            });
    }
    /**
     * If we have more than 3 participants joining we need to do something more to announce them
     * appropriately.
     *
     * We don't want to announce every name when more than 3 participants join at once so
     * we parse out the first 3 names we have and announce those with the number of others.
     */
    const numberOfExtraParticipants = sortedParticipants.length - 3;
    return _formatString(direction === 'joined' ? strings.manyParticipantsJoined : strings.manyParticipantsLeft, {
        displayName1: (_p = (_o = sortedParticipants[0]) === null || _o === void 0 ? void 0 : _o.displayName) !== null && _p !== void 0 ? _p : strings.unnamedParticipantString,
        displayName2: (_r = (_q = sortedParticipants[1]) === null || _q === void 0 ? void 0 : _q.displayName) !== null && _r !== void 0 ? _r : strings.unnamedParticipantString,
        displayName3: (_t = (_s = sortedParticipants[2]) === null || _s === void 0 ? void 0 : _s.displayName) !== null && _t !== void 0 ? _t : strings.unnamedParticipantString,
        numOfParticipants: numberOfExtraParticipants.toString()
    });
};
/**
 * determines if the media gallery should be replaced by the dtmf dialer
 * @param callees Target callees to determine if the dtmf dialer should be shown
 * @param remoteParticipants Remote participants to determine if the dtmf dialer should be shown if there are participants in the call
 * when joining
 * @returns whether the dialer should be the gallery content or not
 */
export const showDtmfDialer = (callees, remoteParticipants, dialerOptions) => {
    let showDtmfDialerAuto = false;
    if (typeof dialerOptions === 'object' && 'dialerBehavior' in dialerOptions) {
        const hideDtmfDialerAlways = dialerOptions.dialerBehavior && dialerOptions.dialerBehavior === 'alwaysHide';
        const showDtmfDialerAlways = dialerOptions.dialerBehavior === 'alwaysShow';
        showDtmfDialerAuto = dialerOptions.dialerBehavior === 'autoShow' ? true : false;
        if (showDtmfDialerAlways) {
            return true;
        }
        if (hideDtmfDialerAlways) {
            return false;
        }
    }
    let showDtmfDialer = false;
    /**
     * We also want to check to see if the option is undefined. If this is the case we want this function
     * to fallback on the original logic so that it will also render the callControls to show and hide the dialpad
     * for the user.
     */
    if (showDtmfDialerAuto || dialerOptions === undefined || dialerOptions === false) {
        callees === null || callees === void 0 ? void 0 : callees.forEach(callee => {
            if (isMicrosoftTeamsAppIdentifier(callee) || isPhoneNumberIdentifier(callee)) {
                showDtmfDialer = true;
            }
        });
        if (remoteParticipants) {
            remoteParticipants.forEach(participant => {
                if (!('phoneNumber' in participant.identifier || 'teamsAppId' in participant.identifier)) {
                    showDtmfDialer = false;
                }
            });
        }
    }
    return showDtmfDialer;
};
//# sourceMappingURL=MediaGalleryUtils.js.map