var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import { parseJwt } from 'genesys-cloud-streaming-client';
import BaseSessionHandler from './base-session-handler';
import { SessionTypes, SdkErrorTypes } from '../types/enums';
import { checkAllTracksHaveEnded } from '../media/media-utils';
import { createAndEmitSdkError, isAcdJid } from '../utils';
export class ScreenShareSessionHandler extends BaseSessionHandler {
    constructor() {
        super(...arguments);
        this.sessionType = SessionTypes.acdScreenShare;
    }
    shouldHandleSessionByJid(jid) {
        return isAcdJid(jid);
    }
    handleConversationUpdate(_update, _sessions) {
        /* no-op */
        return;
    }
    startSession(_startParams) {
        return __awaiter(this, void 0, void 0, function* () {
            const { jwt, conversation, sourceCommunicationId } = this.sdk._customerData;
            const jid = parseJwt(jwt).data.jid;
            const opts = {
                jid,
                conversationId: conversation.id,
                sourceCommunicationId: sourceCommunicationId,
                mediaPurpose: 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(yield 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 });
            yield this.sdk._streamingConnection.webrtcSessions.initiateRtcSession(opts);
            return this._screenStreamPromise;
        });
    }
    handlePropose(pendingSession) {
        const _super = Object.create(null, {
            handlePropose: { get: () => super.handlePropose }
        });
        return __awaiter(this, void 0, void 0, function* () {
            yield _super.handlePropose.call(this, pendingSession);
            yield this.proceedWithSession(pendingSession);
        });
    }
    onTrackEnd(session) {
        this.log('debug', 'Track ended');
        if (checkAllTracksHaveEnded(session._screenShareStream)) {
            return this.endSession(session.conversationId, session);
        }
    }
    handleSessionInit(session) {
        const _super = Object.create(null, {
            handleSessionInit: { get: () => super.handleSessionInit },
            endSession: { get: () => super.endSession }
        });
        return __awaiter(this, void 0, void 0, function* () {
            try {
                yield _super.handleSessionInit.call(this, 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 createAndEmitSdkError.call(this.sdk, 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 createAndEmitSdkError.call(this.sdk, SdkErrorTypes.session, errMsg, sessionInfo);
                }
                const stream = yield 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);
                yield this.addMediaToSession(session, stream);
                yield this.acceptSession(session, { conversationId: session.conversationId });
            }
            catch (err) {
                yield _super.endSession.call(this, session.conversationId, session);
                /* attempt to clean up any streams that may have been created */
                try {
                    this.endTracks(yield this._screenStreamPromise);
                }
                catch (error) {
                    /* no-op: if the promise rejected, we don't care at this point */
                }
                this._screenStreamPromise = null;
                throw createAndEmitSdkError.call(this.sdk, 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 createAndEmitSdkError.call(this.sdk, SdkErrorTypes.not_supported, 'Cannot update outgoing media for acd screen share sessions');
    }
}
export default ScreenShareSessionHandler;
//# sourceMappingURL=screen-share-session-handler.js.map