"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ScreenShareSessionHandler = void 0;
const genesys_cloud_streaming_client_1 = require("genesys-cloud-streaming-client");
const base_session_handler_1 = __importDefault(require("./base-session-handler"));
const enums_1 = require("../types/enums");
const media_utils_1 = require("../media/media-utils");
const utils_1 = require("../utils");
class ScreenShareSessionHandler extends base_session_handler_1.default {
    constructor() {
        super(...arguments);
        this.sessionType = enums_1.SessionTypes.acdScreenShare;
    }
    shouldHandleSessionByJid(jid) {
        return (0, utils_1.isAcdJid)(jid);
    }
    handleConversationUpdate(_update, _sessions) {
        /* no-op */
        return;
    }
    async startSession(_startParams) {
        const { jwt, conversation, sourceCommunicationId } = this.sdk._customerData;
        const jid = (0, genesys_cloud_streaming_client_1.parseJwt)(jwt).data.jid;
        const opts = {
            jid,
            conversationId: conversation.id,
            sourceCommunicationId: sourceCommunicationId,
            mediaPurpose: enums_1.SessionTypes.acdScreenShare,
            sessionType: this.sessionType
        };
        this.log('info', 'starting acd screen share session', opts);
        /* if we had existing media, clean it up */
        try {
            this.endTracks(await this._screenStreamPromise);
        }
        catch (error) {
            /* no-op: it just means the last promise had rejected, we don't care about that error now */
        }
        this._screenStreamPromise = null;
        /* request the display now, but handle it on session-init */
        this._screenStreamPromise = this.sdk.media.startDisplayMedia({ conversationId: conversation.id });
        await this.sdk._streamingConnection.webrtcSessions.initiateRtcSession(opts);
        return this._screenStreamPromise;
    }
    async handlePropose(pendingSession) {
        await super.handlePropose(pendingSession);
        await this.proceedWithSession(pendingSession);
    }
    onTrackEnd(session) {
        this.log('debug', 'Track ended');
        if ((0, media_utils_1.checkAllTracksHaveEnded)(session._screenShareStream)) {
            return this.endSession(session.conversationId, session);
        }
    }
    async handleSessionInit(session) {
        try {
            await super.handleSessionInit(session);
            session.on('terminated', () => {
                /* just in case our session termintated, but didn't set _screenShareStream */
                this.endTracks(session._screenShareStream);
                /* cleanup our local state */
                this._screenStreamPromise = null;
            });
            if (!this.sdk.isGuest) {
                throw utils_1.createAndEmitSdkError.call(this.sdk, enums_1.SdkErrorTypes.not_supported, 'Screen share sessions not supported for authenticated users');
            }
            const sessionInfo = { sessionId: session.id, conversationId: session.conversationId, sessionType: this.sessionType };
            if (!this._screenStreamPromise) {
                const errMsg = 'No pending or active screen share media promise';
                throw utils_1.createAndEmitSdkError.call(this.sdk, enums_1.SdkErrorTypes.session, errMsg, sessionInfo);
            }
            const stream = await this._screenStreamPromise;
            session._screenShareStream = stream;
            stream.getTracks().forEach((track) => {
                track.addEventListener('ended', this.onTrackEnd.bind(this, session));
            });
            this.log('debug', 'Adding stream to the session and setting it to _screenShareStream', sessionInfo);
            await this.addMediaToSession(session, stream);
            await this.acceptSession(session, { conversationId: session.conversationId });
        }
        catch (err) {
            await super.endSession(session.conversationId, session);
            /* attempt to clean up any streams that may have been created */
            try {
                this.endTracks(await this._screenStreamPromise);
            }
            catch (error) {
                /* no-op: if the promise rejected, we don't care at this point */
            }
            this._screenStreamPromise = null;
            throw utils_1.createAndEmitSdkError.call(this.sdk, enums_1.SdkErrorTypes.session, 'Screen share session init failed', err);
        }
    }
    updateOutgoingMedia(session, _options) {
        this.log('warn', 'Cannot update outgoing media for acd screen share sessions', { sessionId: session.id, sessionType: session.sessionType });
        throw utils_1.createAndEmitSdkError.call(this.sdk, enums_1.SdkErrorTypes.not_supported, 'Cannot update outgoing media for acd screen share sessions');
    }
}
exports.ScreenShareSessionHandler = ScreenShareSessionHandler;
exports.default = ScreenShareSessionHandler;
//# sourceMappingURL=screen-share-session-handler.js.map