// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { toFlatCommunicationIdentifier } from "../../acs-ui-common/src";
import { convertSdkRemoteStreamToDeclarativeRemoteStream } from './Converter';
import { RemoteVideoStreamSubscriber } from './RemoteVideoStreamSubscriber';
import { disposeView } from './StreamUtils';
/**
 * Keeps track of the listeners assigned to a particular participant because when we get an event from SDK, it doesn't
 * tell us which participant it is for. If we keep track of this then we know which participant in the state that needs
 * an update and also which property of that participant. Also we can use this when unregistering to a participant.
 */
export class ParticipantSubscriber {
    constructor(callIdRef, participant, context, internalContext) {
        this.subscribe = () => {
            this._participant.on('stateChanged', this.stateChanged);
            this._participant.on('isMutedChanged', this.isMutedChanged);
            this._participant.on('displayNameChanged', this.displayNameChanged);
            this._participant.on('isSpeakingChanged', this.isSpeakingChanged);
            this._participant.on('videoStreamsUpdated', this.videoStreamsUpdated);
            this._participant.on('roleChanged', this.roleChanged);
            if (this._participant.videoStreams.length > 0) {
                for (const stream of this._participant.videoStreams) {
                    this._internalContext.setRemoteRenderInfo(this._callIdRef.callId, this._participantKey, stream.id, stream, 'NotRendered', undefined);
                    this.addRemoteVideoStreamSubscriber(stream);
                }
                this._context.setRemoteVideoStreams(this._callIdRef.callId, this._participantKey, this._participant.videoStreams.map(convertSdkRemoteStreamToDeclarativeRemoteStream), []);
            }
        };
        this.unsubscribe = () => {
            this._participant.off('stateChanged', this.stateChanged);
            this._participant.off('isMutedChanged', this.isMutedChanged);
            this._participant.off('displayNameChanged', this.displayNameChanged);
            this._participant.off('isSpeakingChanged', this.isSpeakingChanged);
            this._participant.off('videoStreamsUpdated', this.videoStreamsUpdated);
            this._participant.off('roleChanged', this.roleChanged);
            // If unsubscribing it means the participant left the call. If they have any rendering streams we should stop them
            // as it doesn't make sense to render for an ended participant.
            if (this._participant.videoStreams.length > 0) {
                for (const stream of this._participant.videoStreams) {
                    disposeView(this._context, this._internalContext, this._callIdRef.callId, this._participantKey, convertSdkRemoteStreamToDeclarativeRemoteStream(stream));
                    this._internalContext.deleteRemoteRenderInfo(this._callIdRef.callId, this._participantKey, stream.id);
                }
            }
        };
        this.addRemoteVideoStreamSubscriber = (remoteVideoStream) => {
            var _a;
            (_a = this._remoteVideoStreamSubscribers.get(remoteVideoStream.id)) === null || _a === void 0 ? void 0 : _a.unsubscribe();
            this._remoteVideoStreamSubscribers.set(remoteVideoStream.id, new RemoteVideoStreamSubscriber(this._callIdRef, this._participantKey, remoteVideoStream, this._context));
        };
        this.stateChanged = () => {
            this._context.setParticipantState(this._callIdRef.callId, this._participantKey, this._participant.state);
        };
        this.isMutedChanged = () => {
            this._context.setParticipantIsMuted(this._callIdRef.callId, this._participantKey, this._participant.isMuted);
        };
        this.roleChanged = () => {
            this._context.setParticipantRole(this._callIdRef.callId, this._participantKey, this._participant.role);
        };
        this.displayNameChanged = () => {
            this._context.setParticipantDisplayName(this._callIdRef.callId, this._participantKey, this._participant.displayName || '');
        };
        this.isSpeakingChanged = () => {
            this._context.setParticipantIsSpeaking(this._callIdRef.callId, this._participantKey, this._participant.isSpeaking);
        };
        this.videoStreamsUpdated = (event) => {
            var _a;
            for (const stream of event.removed) {
                (_a = this._remoteVideoStreamSubscribers.get(stream.id)) === null || _a === void 0 ? void 0 : _a.unsubscribe();
                disposeView(this._context, this._internalContext, this._callIdRef.callId, this._participantKey, convertSdkRemoteStreamToDeclarativeRemoteStream(stream));
                this._internalContext.deleteRemoteRenderInfo(this._callIdRef.callId, this._participantKey, stream.id);
            }
            for (const stream of event.added) {
                this._internalContext.setRemoteRenderInfo(this._callIdRef.callId, this._participantKey, stream.id, stream, 'NotRendered', undefined);
                this.addRemoteVideoStreamSubscriber(stream);
            }
            this._context.setRemoteVideoStreams(this._callIdRef.callId, this._participantKey, event.added.map(convertSdkRemoteStreamToDeclarativeRemoteStream), event.removed.map((stream) => stream.id));
        };
        this._callIdRef = callIdRef;
        this._participant = participant;
        this._context = context;
        this._internalContext = internalContext;
        this._participantKey = toFlatCommunicationIdentifier(this._participant.identifier);
        this._remoteVideoStreamSubscribers = new Map();
        this.subscribe();
    }
}
//# sourceMappingURL=ParticipantSubscriber.js.map