// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { clearCallRelatedState, ProxyCallAgentCommon } from './CallAgentDeclarativeCommon';
import { _isTeamsCall, _isTeamsCallAgent } from './TypeGuards';
import { teamsCallDeclaratify } from './TeamsCallDeclarative';
/**
 * ProxyTeamsCallAgent proxies TeamsCallAgent and saves any returned state in the given context. It will subscribe to all state
 * updates in the TeamsCallAgent and in the contained TeamsCalls and RemoteParticipants. When dispose is called it will
 * unsubscribe from all state updates.
 */
class ProxyTeamsCallAgent extends ProxyCallAgentCommon {
    constructor(callAgent, context, internalContext) {
        super(context, internalContext);
        this.subscribe = () => {
            this._callAgent.on('callsUpdated', this.callsUpdated);
            this._callAgent.on('incomingCall', this.incomingCall);
            // There could be scenario that when ProxyTeamsCallAgent is created that the given CallAgent already has TeamsCalls. In this
            // case we need to make sure to subscribe to those already existing Calls.
            for (const call of this._callAgent.calls) {
                this.addCall(call);
            }
        };
        this.unsubscribe = () => {
            this._callAgent.off('callsUpdated', this.callsUpdated);
            this._callAgent.off('incomingCall', this.incomingCall);
            this.unregisterSubscriber();
        };
        this._callAgent = callAgent;
        this.subscribe();
    }
    callDeclaratify(call, context) {
        if (_isTeamsCall(call)) {
            return teamsCallDeclaratify(call, context);
        }
        throw new Error('Not reachable code, DeclarativeTeamsCallAgent.callDeclaratify must be called with an TeamsCall.');
    }
    startCall(agent, args) {
        if (_isTeamsCallAgent(agent)) {
            return agent.startCall(...args);
        }
        throw new Error('Not reachable code, DeclarativeTeamsCallAgent.startCall must be called with an TeamsCallAgent.');
    }
    joinCall(agent, args) {
        if (_isTeamsCallAgent(agent)) {
            return agent.join(...args);
        }
        throw new Error('Not reachable code, DeclarativeTeamsCallAgent.joinCall must be called with an TeamsCallAgent.');
    }
    agentSubscribe(agent, args) {
        if (_isTeamsCallAgent(agent)) {
            agent.on(...args);
            return;
        }
        throw new Error('Not reachable code, DeclarativeTeamsCallAgent.agentSubscribe must be called with an TeamsCallAgent.');
    }
    agentUnsubscribe(agent, args) {
        if (_isTeamsCallAgent(agent)) {
            agent.off(...args);
            return;
        }
        throw new Error('Not reachable code, DeclarativeTeamsCallAgent.agentUnsubscribe must be called with an TeamsCallAgent.');
    }
    get(target, prop) {
        return super.getCommon(target, prop);
    }
}
/**
 * Creates a declarative CallAgent by proxying TeamsCallAgent with ProxyTeamsCallAgent which will track state updates by updating
 * the given context.
 *
 * @param callAgent - TeamsCallAgent from SDK
 * @param context - CallContext from StatefulCallClient
 * @param internalContext- InternalCallContext from StatefulCallClient
 */
export const teamsCallAgentDeclaratify = (callAgent, context, internalContext) => {
    clearCallRelatedState(context, internalContext);
    return new Proxy(callAgent, new ProxyTeamsCallAgent(callAgent, context, internalContext));
};
//# sourceMappingURL=TeamsCallAgentDeclarative.js.map