// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
/**
 * Create a record for when the notification was most recently dismissed for tracking dismissed notifications.
 *
 * @private
 */
export const useTrackedCapabilityChangedNotifications = (capabilitiesChangedAndRoleInfo) => {
    const [trackedCapabilityChangedNotifications, setTrackedCapabilityChangedNotifications] = useState({});
    const activeNotifications = useRef({});
    useEffect(() => {
        activeNotifications.current = updateLatestCapabilityChangedNotificationMap(capabilitiesChangedAndRoleInfo, activeNotifications.current);
        setTrackedCapabilityChangedNotifications(prev => updateTrackedCapabilityChangedNotificationsWithActiveNotifications(prev, Object.values(activeNotifications.current)));
    }, [capabilitiesChangedAndRoleInfo]);
    const onDismissCapabilityChangedNotification = useCallback((notification) => {
        setTrackedCapabilityChangedNotifications(prev => trackCapabilityChangedNotificationAsDismissed(notification.capabilityName, prev));
    }, []);
    const latestCapabilityChangedNotifications = useMemo(() => filterLatestCapabilityChangedNotifications(Object.values(activeNotifications.current), trackedCapabilityChangedNotifications), [trackedCapabilityChangedNotifications]);
    return {
        capabilitiesChangedNotifications: latestCapabilityChangedNotifications,
        onDismissNotification: onDismissCapabilityChangedNotification
    };
};
/**
 * Take the set of active notifications, and filter to only those that are newer than previously dismissed notifications or have never been dismissed.
 *
 * @private
 */
export const filterLatestCapabilityChangedNotifications = (activeNotifications, trackedNotifications) => {
    const filteredNotifications = activeNotifications.filter(activeNotification => {
        const trackedNotification = trackedNotifications[activeNotification.capabilityName];
        return !trackedNotification || !trackedNotification.lastDismissedAt || trackedNotification.lastDismissedAt < trackedNotification.mostRecentlyActive;
    });
    return filteredNotifications;
};
/**
 * Maintain a record of the most recently active notification for each capability name.
 *
 * @private
 */
export const updateTrackedCapabilityChangedNotificationsWithActiveNotifications = (existingTrackedNotifications, activeNotifications) => {
    var _a, _b;
    const trackedNotifications = {};
    // Only care about active notifications. If notifications are no longer active we do not track that they have been previously dismissed.
    for (const activeNotification of activeNotifications) {
        const existingTrackedNotification = existingTrackedNotifications[activeNotification.capabilityName];
        trackedNotifications[activeNotification.capabilityName] = {
            mostRecentlyActive: (_b = (_a = activeNotification.timestamp) !== null && _a !== void 0 ? _a : existingTrackedNotification === null || existingTrackedNotification === void 0 ? void 0 : existingTrackedNotification.mostRecentlyActive) !== null && _b !== void 0 ? _b : new Date(Date.now()),
            lastDismissedAt: existingTrackedNotification === null || existingTrackedNotification === void 0 ? void 0 : existingTrackedNotification.lastDismissedAt
        };
    }
    return trackedNotifications;
};
/**
 * Create a record for when the notification was most recently dismissed for tracking dismissed notifications.
 *
 * @private
 */
export const trackCapabilityChangedNotificationAsDismissed = (capabilityName, trackedNotifications) => {
    const now = new Date(Date.now());
    const existingNotification = trackedNotifications[capabilityName];
    return Object.assign(Object.assign({}, trackedNotifications), { [capabilityName]: Object.assign(Object.assign({}, (existingNotification || {})), { lastDismissedAt: now }) });
};
const updateLatestCapabilityChangedNotificationMap = (capabilitiesChangedInfoAndRole, activeNotifications) => {
    var _a, _b;
    if (!capabilitiesChangedInfoAndRole.capabilitiesChangeInfo) {
        return activeNotifications;
    }
    for (const [capabilityKey, newCapabilityValue] of Object.entries(capabilitiesChangedInfoAndRole.capabilitiesChangeInfo.newValue)) {
        // Cast is safe because we are iterating over the enum keys on the object.entries where
        // newCapabilityValue typing is correctly returned. Object.entries limitations
        // always returns string for the key
        const capabilityName = capabilityKey;
        // If the active notification for a capability has the same `isPresent` value and the same reason as the new
        // capability value from the SDK then we will not create a new notification to avoid redundancy
        if (activeNotifications[capabilityName] && newCapabilityValue.isPresent === ((_a = activeNotifications[capabilityName]) === null || _a === void 0 ? void 0 : _a.isPresent) && capabilitiesChangedInfoAndRole.capabilitiesChangeInfo.reason === ((_b = activeNotifications[capabilityName]) === null || _b === void 0 ? void 0 : _b.changedReason)) {
            continue;
        }
        // All initial values of capabilities are not present with reason 'FeatureNotSupported'. So we should not show a
        // notification for them when they initially become present at the start of the call
        const oldCapabilityValue = capabilitiesChangedInfoAndRole.capabilitiesChangeInfo.oldValue[capabilityName];
        if (newCapabilityValue.isPresent === true && (oldCapabilityValue === null || oldCapabilityValue === void 0 ? void 0 : oldCapabilityValue.isPresent) === false && (oldCapabilityValue === null || oldCapabilityValue === void 0 ? void 0 : oldCapabilityValue.reason) === 'FeatureNotSupported' && capabilitiesChangedInfoAndRole.capabilitiesChangeInfo.reason === 'MeetingOptionOrOrganizerPolicyChanged') {
            continue;
        }
        // Do not show the first time the screenshare capability is present when the user's role is resolved to mirror
        // Teams behaviour
        if (capabilityName === 'shareScreen' && activeNotifications['shareScreen'] === undefined && newCapabilityValue.isPresent === true && (oldCapabilityValue === null || oldCapabilityValue === void 0 ? void 0 : oldCapabilityValue.isPresent) === false && capabilitiesChangedInfoAndRole.capabilitiesChangeInfo.reason === 'RoleChanged') {
            continue;
        }
        const newCapabilityChangeNotification = {
            capabilityName: capabilityName,
            isPresent: newCapabilityValue.isPresent,
            changedReason: capabilitiesChangedInfoAndRole.capabilitiesChangeInfo.reason,
            role: capabilitiesChangedInfoAndRole.participantRole,
            timestamp: new Date(Date.now())
        };
        activeNotifications[capabilityName] = newCapabilityChangeNotification;
    }
    return activeNotifications;
};
//# sourceMappingURL=TrackCapabilityChangedNotifications.js.map