// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { CallIdHistory } from './CallIdHistory';
import { LocalVideoStreamVideoEffectsSubscriber } from './LocalVideoStreamVideoEffectsSubscriber';
import { Features } from '@azure/communication-calling';
/**
 * Contains internal data used between different Declarative components to share data.
 */
export class InternalCallContext {
    constructor() {
        // <CallId, <ParticipantKey, <StreamId, RemoteRenderInfo>>
        this._remoteRenderInfos = new Map();
        // <CallId, <MediaStreamType, LocalRenderInfo>>.
        this._localRenderInfos = new Map();
        // <CallId, <featureName, <MediaStreamType, CallFeatureRenderInfo>>>.
        this._callFeatureRenderInfos = new Map();
        // Used for keeping track of rendered LocalVideoStreams that are not part of a Call.
        this._unparentedRenderInfos = new Map();
        this._callIdHistory = new CallIdHistory();
        // Used for keeping track of video effects subscribers that are not part of a Call.
        // The key is the stream ID. We assume each stream ID
        this._unparentedViewVideoEffectsSubscriber = new Map();
    }
    setCallId(newCallId, oldCallId) {
        this._callIdHistory.updateCallIdHistory(newCallId, oldCallId);
        const remoteRenderInfos = this._remoteRenderInfos.get(oldCallId);
        if (remoteRenderInfos) {
            this._remoteRenderInfos.delete(oldCallId);
            this._remoteRenderInfos.set(newCallId, remoteRenderInfos);
        }
        const localRenderInfos = this._localRenderInfos.get(oldCallId);
        if (localRenderInfos) {
            this._localRenderInfos.delete(oldCallId);
            this._localRenderInfos.set(newCallId, localRenderInfos);
        }
        const callFeatureRenderInfos = this._callFeatureRenderInfos.get(oldCallId);
        if (callFeatureRenderInfos) {
            this._callFeatureRenderInfos.delete(oldCallId);
            this._callFeatureRenderInfos.set(newCallId, callFeatureRenderInfos);
        }
    }
    getCallIds() {
        return this._remoteRenderInfos.keys();
    }
    getRemoteRenderInfoForCall(callId) {
        return this._remoteRenderInfos.get(this._callIdHistory.latestCallId(callId));
    }
    getRemoteRenderInfoForParticipant(callId, participantKey, streamId) {
        const callRenderInfos = this._remoteRenderInfos.get(this._callIdHistory.latestCallId(callId));
        if (!callRenderInfos) {
            return undefined;
        }
        const participantRenderInfos = callRenderInfos.get(participantKey);
        if (!participantRenderInfos) {
            return undefined;
        }
        return participantRenderInfos.get(streamId);
    }
    setRemoteRenderInfo(callId, participantKey, streamId, stream, status, renderer) {
        let callRenderInfos = this._remoteRenderInfos.get(this._callIdHistory.latestCallId(callId));
        if (!callRenderInfos) {
            callRenderInfos = new Map();
            this._remoteRenderInfos.set(this._callIdHistory.latestCallId(callId), callRenderInfos);
        }
        let participantRenderInfos = callRenderInfos.get(participantKey);
        if (!participantRenderInfos) {
            participantRenderInfos = new Map();
            callRenderInfos.set(participantKey, participantRenderInfos);
        }
        participantRenderInfos.set(streamId, {
            stream,
            status,
            renderer
        });
    }
    deleteRemoteRenderInfo(callId, participantKey, streamId) {
        const callRenderInfos = this._remoteRenderInfos.get(this._callIdHistory.latestCallId(callId));
        if (!callRenderInfos) {
            return;
        }
        const participantRenderInfos = callRenderInfos.get(participantKey);
        if (!participantRenderInfos) {
            return;
        }
        participantRenderInfos.delete(streamId);
    }
    setLocalRenderInfo(callId, streamKey, stream, status, renderer) {
        let localRenderInfosForCall = this._localRenderInfos.get(this._callIdHistory.latestCallId(callId));
        if (!localRenderInfosForCall) {
            localRenderInfosForCall = new Map();
            this._localRenderInfos.set(this._callIdHistory.latestCallId(callId), localRenderInfosForCall);
        }
        localRenderInfosForCall.set(streamKey, {
            stream,
            status,
            renderer
        });
    }
    getLocalRenderInfosForCall(callId) {
        return this._localRenderInfos.get(this._callIdHistory.latestCallId(callId));
    }
    getLocalRenderInfo(callId, streamKey) {
        const localRenderInfosForCall = this._localRenderInfos.get(this._callIdHistory.latestCallId(callId));
        if (!localRenderInfosForCall) {
            return undefined;
        }
        return localRenderInfosForCall.get(streamKey);
    }
    deleteLocalRenderInfo(callId, streamKey) {
        const localRenderInfoForCall = this._localRenderInfos.get(this._callIdHistory.latestCallId(callId));
        if (!localRenderInfoForCall) {
            return;
        }
        localRenderInfoForCall.delete(streamKey);
    }
    getUnparentedRenderInfo(localVideoStream) {
        return this._unparentedRenderInfos.get(localVideoStream.mediaStreamType);
    }
    getUnparentedRenderInfos() {
        return [...this._unparentedRenderInfos].map(([, renderInfo]) => renderInfo.stream);
    }
    setUnparentedRenderInfo(statefulStream, stream, status, renderer) {
        this._unparentedRenderInfos.set(statefulStream.mediaStreamType, {
            stream,
            status,
            renderer
        });
    }
    deleteUnparentedRenderInfo(localVideoStream) {
        var _a;
        (_a = this._unparentedViewVideoEffectsSubscriber.get(localVideoStream.mediaStreamType)) === null || _a === void 0 ? void 0 : _a.unsubscribe();
        this._unparentedRenderInfos.delete(localVideoStream.mediaStreamType);
    }
    subscribeToUnparentedViewVideoEffects(localVideoStream, callContext) {
        var _a;
        {
            // Ensure we aren't setting multiple subscriptions
            (_a = this._unparentedViewVideoEffectsSubscriber.get(localVideoStream.mediaStreamType)) === null || _a === void 0 ? void 0 : _a.unsubscribe();
            this._unparentedViewVideoEffectsSubscriber.set(localVideoStream.mediaStreamType, new LocalVideoStreamVideoEffectsSubscriber({
                parent: 'unparented',
                context: callContext,
                localVideoStream: localVideoStream,
                localVideoStreamEffectsAPI: localVideoStream.feature(Features.VideoEffects)
            }));
        }
    }
    // UnparentedRenderInfos are not cleared as they are not part of the Call state.
    clearCallRelatedState() {
        this._remoteRenderInfos.clear();
        this._localRenderInfos.clear();
        this._callFeatureRenderInfos.clear();
    }
    getCallFeatureRenderInfosForCall(callId) {
        return this._callFeatureRenderInfos.get(this._callIdHistory.latestCallId(callId));
    }
    getCallFeatureRenderInfo(callId, featureNameKey, streamKey) {
        var _a, _b;
        const callFeatureRenderInfosForCall = (_b = (_a = this._callFeatureRenderInfos.get(this._callIdHistory.latestCallId(callId))) === null || _a === void 0 ? void 0 : _a.get(featureNameKey)) === null || _b === void 0 ? void 0 : _b.get(streamKey);
        if (!callFeatureRenderInfosForCall) {
            return undefined;
        }
        return callFeatureRenderInfosForCall;
    }
    setCallFeatureRenderInfo(callId, featureNameKey, streamKey, stream, status, renderer) {
        let callRenderInfos = this._callFeatureRenderInfos.get(this._callIdHistory.latestCallId(callId));
        if (!callRenderInfos) {
            callRenderInfos = new Map();
            // If the callId is not found, create a new map for the callId.
            this._callFeatureRenderInfos.set(this._callIdHistory.latestCallId(callId), callRenderInfos);
        }
        let featureRenderInfos = callRenderInfos.get(featureNameKey);
        if (!featureRenderInfos) {
            featureRenderInfos = new Map();
            callRenderInfos.set(featureNameKey, featureRenderInfos);
        }
        featureRenderInfos.set(streamKey, {
            stream,
            status,
            renderer
        });
    }
    deleteCallFeatureRenderInfo(callId, featureName, streamKey) {
        var _a;
        const callFeatureRenderInfoForCall = this._callFeatureRenderInfos.get(this._callIdHistory.latestCallId(callId));
        if (!callFeatureRenderInfoForCall || !callFeatureRenderInfoForCall.get(featureName)) {
            return;
        }
        (_a = callFeatureRenderInfoForCall.get(featureName)) === null || _a === void 0 ? void 0 : _a.delete(streamKey);
    }
}
//# sourceMappingURL=InternalCallContext.js.map