"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ScreenRecordingSessionHandler = void 0;
const base_session_handler_1 = __importDefault(require("./base-session-handler"));
const enums_1 = require("../types/enums");
const utils_1 = require("../utils");
const rxjs_1 = require("rxjs");
class ScreenRecordingSessionHandler extends base_session_handler_1.default {
    constructor() {
        super(...arguments);
        this.requestedSessions = {};
        this.sessionType = enums_1.SessionTypes.screenRecording;
    }
    shouldHandleSessionByJid(jid) {
        return (0, utils_1.isScreenRecordingJid)(jid);
    }
    handleConversationUpdate() {
        /* no-op */
        return;
    }
    async handlePropose(pendingSession) {
        if (this.sdk._config.autoAcceptPendingScreenRecordingRequests) {
            return this.proceedWithSession(pendingSession);
        }
        // if not auto accepting sessions, emit this event for the consumer to accept
        await super.handlePropose(pendingSession);
    }
    async acceptSession(session, params) {
        const mediaStream = params.mediaStream;
        if (!mediaStream) {
            throw utils_1.createAndEmitSdkError.call(this.sdk, enums_1.SdkErrorTypes.session, `Cannot accept screen recording session without providing a media stream`, { conversationId: session.conversationId, sessionType: this.sessionType });
        }
        if (!params.screenRecordingMetadatas?.length) {
            throw utils_1.createAndEmitSdkError.call(this.sdk, enums_1.SdkErrorTypes.not_supported, 'acceptSession must be called with a `screenRecordingMetadatas` property for screen recording sessions');
        }
        session._outboundStream = mediaStream;
        let addMediaPromise = Promise.resolve();
        mediaStream.getTracks().forEach((track) => {
            addMediaPromise = addMediaPromise.then(() => {
                this.sdk.logger.info('Adding screen track to session', { trackId: track.id, label: track.label, conversationId: session.conversationId, sessionType: this.sessionType });
                return session.pc.addTrack(track);
            });
        });
        await addMediaPromise;
        this.sendMetadataWhenSessionConnects(session, params.screenRecordingMetadatas);
        await super.acceptSession(session, params);
    }
    sendMetadataWhenSessionConnects(session, metadatas) {
        // We really only want to ignore the error handling (because that should never execute), but putting an ignore closer to that line doesn't properly ignore it
        /* istanbul ignore next */
        (0, rxjs_1.fromEvent)(session.peerConnection, 'connectionstatechange')
            .pipe((0, rxjs_1.takeWhile)(() => {
            return !(0, utils_1.isPeerConnectionDisconnected)(session.peerConnection.connectionState);
        }), (0, rxjs_1.filter)(() => {
            return session.peerConnection.connectionState === 'connected';
        }), (0, rxjs_1.take)(1)).subscribe({
            next: async () => await this.updateScreenRecordingMetadatas(session, metadatas),
            error: (e) => this._logSubscriptionError(e)
        });
    }
    /* istanbul ignore next */
    _logSubscriptionError(_) {
        // This is for testing thrown exceptions with an RXJS subscription
    }
    async endSession(conversationId, _session, _reason) {
        throw utils_1.createAndEmitSdkError.call(this.sdk, enums_1.SdkErrorTypes.not_supported, `sessionType ${this.sessionType} must be ended remotely`, { conversationId });
    }
    updateOutgoingMedia(session, _options) {
        this.log('warn', 'Cannot update outgoing media for screen recording sessions', { sessionId: session.id, sessionType: session.sessionType });
        throw utils_1.createAndEmitSdkError.call(this.sdk, enums_1.SdkErrorTypes.not_supported, 'Cannot update outgoing media for screen recording sessions');
    }
    updateScreenRecordingMetadatas(session, metadatas) {
        this.log('info', 'sending screen metadatas', { conversationId: session.conversationId, sessionId: session.id, metadatas });
        metadatas.forEach((meta) => {
            // adding _trackId because I don't want to add this to the public interface
            meta._trackId = meta.trackId;
            const transceiver = session.pc.getTransceivers()
                .find((transceiver) => transceiver.sender.track?.id === meta.trackId);
            if (!transceiver) {
                this.log('warn', 'Failed to find transceiver for screen recording track', { conversationId: session.conversationId, sessionId: session.id, trackId: meta.trackId });
                return;
            }
            meta.trackId = transceiver.mid;
        });
        const data = JSON.stringify({
            participantJid: (0, utils_1.getBareJid)(this.sdk),
            metaData: metadatas,
            roomId: session.originalRoomJid,
            conversationId: session.conversationId
        });
        let url = '/recordings/screensessions/metadata';
        const { accessToken, jwt } = this.sdk._config;
        if (this.sdk.isJwtAuth) {
            url += '/backgroundassistant';
        }
        return utils_1.requestApiWithRetry
            .call(this.sdk, url, {
            method: 'post',
            authToken: accessToken || jwt,
            data,
        })
            .promise.then(() => {
            this.log('info', 'Screen recording metadata sent.', {
                conversationId: session.conversationId,
                sessionId: session.id,
                metadatas,
            });
        })
            .catch((e) => {
            this.log('error', 'Failed to send screen recording metadata.', {
                error: e,
                conversationId: session.conversationId,
                sessionId: session.id,
                metadatas,
            });
            throw e;
        });
    }
}
exports.ScreenRecordingSessionHandler = ScreenRecordingSessionHandler;
exports.default = ScreenRecordingSessionHandler;
//# sourceMappingURL=screen-recording-session-handler.js.map