"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Video = exports.initVideoCallData = void 0;
const tslib_1 = require("tslib");
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const Peer = require("simple-peer");
const immer_1 = require("immer");
const constants_1 = require("../constants");
const sendVideoCallNotification_1 = require("./helpers/sendVideoCallNotification");
const mediaToggle_1 = require("./helpers/mediaToggle");
const isJSON_1 = require("./helpers/isJSON");
const getIceServerConfig_1 = require("./helpers/getIceServerConfig");
const types_1 = require("../types");
const getIncomingIndexFromAddress_1 = require("./helpers/getIncomingIndexFromAddress");
const getConnectedAddresses_1 = require("./helpers/getConnectedAddresses");
const getConnectToAddresses_1 = require("./helpers/getConnectToAddresses");
const constants_2 = require("../payloads/constants");
exports.initVideoCallData = {
    meta: {
        chatId: '',
        initiator: {
            address: '',
            signal: null,
        },
        broadcast: {
            livepeerInfo: null,
            hostAddress: '',
            coHostAddress: '',
        },
    },
    local: {
        stream: null,
        audio: null,
        video: null,
        address: '',
    },
    // TODO: Remove the default element in incoming array
    incoming: [
        {
            stream: null,
            audio: null,
            video: null,
            address: '',
            status: types_1.VideoCallStatus.UNINITIALIZED,
            retryCount: 0,
        },
    ],
};
class Video {
    constructor({ signer, chainId, pgpPrivateKey, env = constants_1.default.ENV.PROD, setData, callType = constants_2.VIDEO_CALL_TYPE.PUSH_VIDEO, onReceiveStream = () => tslib_1.__awaiter(this, void 0, void 0, function* () {
        return Promise.resolve();
    }), }) {
        // storing the peer instance
        this.peerInstances = {};
        this.signer = signer;
        this.chainId = chainId;
        this.pgpPrivateKey = pgpPrivateKey;
        this.env = env;
        this.callType = callType;
        this.onReceiveStream = onReceiveStream;
        // init the react state
        setData(() => exports.initVideoCallData);
        // init the class variable
        this.data = exports.initVideoCallData;
        // set the state updating function
        this.setData = function (fn) {
            // update the react state
            setData(fn);
            // update the class variable
            this.data = fn(this.data);
        };
    }
    create(options) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { audio = true, video = true, stream = null } = options || {};
            try {
                const localStream = stream !== null
                    ? stream // for backend
                    : yield navigator.mediaDevices.getUserMedia({
                        // for frontend
                        video,
                        audio,
                    });
                this.setData((oldData) => {
                    return (0, immer_1.produce)(oldData, (draft) => {
                        draft.local.stream = localStream;
                        draft.local.video = video;
                        draft.local.audio = audio;
                    });
                });
            }
            catch (err) {
                console.error('error in create', err);
            }
        });
    }
    request(options) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { senderAddress, recipientAddress, chatId, rules, onReceiveMessage, retry = false, details, } = options || {};
            const recipientAddresses = Array.isArray(recipientAddress)
                ? recipientAddress
                : [recipientAddress];
            for (const recipientAddress of recipientAddresses) {
                try {
                    // set videoCallInfo state with status 1 (call initiated)
                    this.setData((oldData) => {
                        return (0, immer_1.produce)(oldData, (draft) => {
                            draft.local.address = senderAddress;
                            draft.meta.chatId = chatId !== null && chatId !== void 0 ? chatId : rules.access.data;
                            draft.meta.initiator.address = senderAddress;
                            const incomingIndex = (0, getIncomingIndexFromAddress_1.default)(oldData.incoming, recipientAddress);
                            if (incomingIndex === -1) {
                                draft.incoming.push({
                                    stream: null,
                                    audio: null,
                                    video: null,
                                    address: recipientAddress,
                                    status: retry
                                        ? types_1.VideoCallStatus.RETRY_INITIALIZED
                                        : types_1.VideoCallStatus.INITIALIZED,
                                    retryCount: retry ? 1 : 0,
                                });
                            }
                            else {
                                draft.incoming[incomingIndex].address = recipientAddress;
                                draft.incoming[incomingIndex].status = retry
                                    ? types_1.VideoCallStatus.RETRY_INITIALIZED
                                    : types_1.VideoCallStatus.INITIALIZED;
                                draft.incoming[incomingIndex].retryCount += retry ? 1 : 0;
                            }
                        });
                    });
                    // fetching the iceServers config
                    const iceServerConfig = yield (0, getIceServerConfig_1.getIceServerConfig)(this.env);
                    this.peerInstances[recipientAddress] = new Peer({
                        initiator: true,
                        trickle: false,
                        stream: this.data.local.stream,
                        config: {
                            iceServers: iceServerConfig,
                        },
                    });
                    this.peerInstances[recipientAddress].on('signal', (data) => {
                        this.setData((oldData) => {
                            return (0, immer_1.produce)(oldData, (draft) => {
                                draft.meta.initiator.signal = data;
                            });
                        });
                        // sending notification to the recipientAddress with video call signaling data
                        (0, sendVideoCallNotification_1.default)({
                            signer: this.signer,
                            chainId: this.chainId,
                            pgpPrivateKey: this.pgpPrivateKey,
                        }, {
                            senderAddress,
                            recipientAddress,
                            status: retry
                                ? types_1.VideoCallStatus.RETRY_INITIALIZED
                                : types_1.VideoCallStatus.INITIALIZED,
                            chatId,
                            rules,
                            signalData: data,
                            env: this.env,
                            callType: this.callType,
                            callDetails: details,
                        });
                    });
                    this.peerInstances[recipientAddress].on('connect', () => {
                        this.peerInstances[recipientAddress].send(`initial message from ${senderAddress}`);
                        this.peerInstances[recipientAddress].send(JSON.stringify({
                            type: 'isVideoOn',
                            value: this.data.local.video,
                        }));
                        this.peerInstances[recipientAddress].send(JSON.stringify({
                            type: 'isAudioOn',
                            value: this.data.local.audio,
                        }));
                        // send the addresses the local peer is connected to remote peer
                        const connectedAddresses = (0, getConnectedAddresses_1.default)({
                            incomingPeers: this.data.incoming,
                        });
                        this.peerInstances[recipientAddress].send(JSON.stringify({
                            type: 'connectedAddresses',
                            value: connectedAddresses,
                        }));
                    });
                    this.peerInstances[recipientAddress].on('data', (data) => {
                        var _a, _b, _c, _d, _e;
                        if ((0, isJSON_1.default)(data)) {
                            const parsedData = JSON.parse(data);
                            if (parsedData.type === 'connectedAddresses') {
                                const receivedConnectedAddresses = parsedData.value;
                                const localConnectedAddresses = (0, getConnectedAddresses_1.default)({
                                    incomingPeers: this.data.incoming,
                                });
                                // find out the address to which local peer is not connected to but the remote peer is
                                // then connect with them
                                const connectToAddresses = (0, getConnectToAddresses_1.default)({
                                    localAddress: senderAddress,
                                    localConnectedAddresses,
                                    receivedConnectedAddresses,
                                });
                                this.request({
                                    senderAddress,
                                    recipientAddress: connectToAddresses,
                                    chatId,
                                    rules,
                                    details: {
                                        type: constants_2.SPACE_REQUEST_TYPE.ESTABLISH_MESH,
                                        data: {},
                                    },
                                });
                            }
                            if (parsedData.type === 'isVideoOn') {
                                this.setData((oldData) => {
                                    return (0, immer_1.produce)(oldData, (draft) => {
                                        const incomingIndex = (0, getIncomingIndexFromAddress_1.default)(oldData.incoming, recipientAddress);
                                        draft.incoming[incomingIndex].video = parsedData.value;
                                    });
                                });
                            }
                            if (parsedData.type === 'isAudioOn') {
                                this.setData((oldData) => {
                                    return (0, immer_1.produce)(oldData, (draft) => {
                                        const incomingIndex = (0, getIncomingIndexFromAddress_1.default)(oldData.incoming, recipientAddress);
                                        draft.incoming[incomingIndex].audio = parsedData.value;
                                    });
                                });
                            }
                            if (parsedData.type === 'endCall') {
                                if (this.callType === constants_2.VIDEO_CALL_TYPE.PUSH_SPACE &&
                                    ((_a = parsedData === null || parsedData === void 0 ? void 0 : parsedData.details) === null || _a === void 0 ? void 0 : _a.type) === constants_2.SPACE_DISCONNECT_TYPE.LEAVE) {
                                    // destroy connection to only the current peer
                                    (_b = this.peerInstances[recipientAddress]) === null || _b === void 0 ? void 0 : _b.destroy();
                                    this.peerInstances[recipientAddress] = null;
                                    this.setData((oldData) => {
                                        return (0, immer_1.produce)(oldData, (draft) => {
                                            const incomingIndex = (0, getIncomingIndexFromAddress_1.default)(oldData.incoming, recipientAddress);
                                            draft.incoming.splice(incomingIndex, 1);
                                        });
                                    });
                                }
                                if (this.callType === constants_2.VIDEO_CALL_TYPE.PUSH_SPACE &&
                                    ((_c = parsedData === null || parsedData === void 0 ? void 0 : parsedData.details) === null || _c === void 0 ? void 0 : _c.type) === constants_2.SPACE_DISCONNECT_TYPE.STOP) {
                                    // destroy connection to all the peers
                                    for (const connectedAddress in this.peerInstances) {
                                        (_d = this.peerInstances[connectedAddress]) === null || _d === void 0 ? void 0 : _d.destroy();
                                        this.peerInstances[connectedAddress] = null;
                                    }
                                    // destroy the local stream
                                    if (this.data.local.stream) {
                                        (0, mediaToggle_1.endStream)(this.data.local.stream);
                                    }
                                    // reset the state
                                    this.setData(() => exports.initVideoCallData);
                                }
                                if (this.callType === constants_2.VIDEO_CALL_TYPE.PUSH_VIDEO) {
                                    (_e = this.peerInstances[recipientAddress]) === null || _e === void 0 ? void 0 : _e.destroy();
                                    this.peerInstances[recipientAddress] = null;
                                    // destroy the local stream
                                    if (this.data.local.stream) {
                                        (0, mediaToggle_1.endStream)(this.data.local.stream);
                                    }
                                    // reset the state
                                    this.setData(() => exports.initVideoCallData);
                                }
                            }
                        }
                        else if (onReceiveMessage) {
                            onReceiveMessage(data);
                        }
                    });
                    this.peerInstances[recipientAddress].on('stream', (currentStream) => {
                        const incomingIndex = (0, getIncomingIndexFromAddress_1.default)(this.data.incoming, recipientAddress);
                        this.onReceiveStream(currentStream, recipientAddress, this.data.incoming[incomingIndex].audio);
                        this.setData((oldData) => {
                            return (0, immer_1.produce)(oldData, (draft) => {
                                draft.incoming[incomingIndex].stream = currentStream;
                            });
                        });
                    });
                }
                catch (err) {
                    console.error('error in request', err);
                }
            }
        });
    }
    acceptRequest(options) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { signalData, senderAddress, recipientAddress, chatId, rules, onReceiveMessage, retry = false, details, } = options || {};
            try {
                // if peerInstance is not null -> acceptRequest/request was called before
                if (this.peerInstances[recipientAddress]) {
                    // to prevent connection error we stop the exec of acceptRequest
                    return Promise.resolve();
                }
                // fetching the iceServers config
                const iceServerConfig = yield (0, getIceServerConfig_1.getIceServerConfig)(this.env);
                // creating peer instance
                this.peerInstances[recipientAddress] = new Peer({
                    initiator: false,
                    trickle: false,
                    stream: this.data.local.stream,
                    config: {
                        iceServers: iceServerConfig,
                    },
                });
                // set videoCallInfo state with status 2 (call received)
                this.setData((oldData) => {
                    return (0, immer_1.produce)(oldData, (draft) => {
                        draft.local.address = senderAddress;
                        draft.meta.chatId = chatId !== null && chatId !== void 0 ? chatId : rules.access.data;
                        draft.meta.initiator.address = senderAddress;
                        const incomingIndex = (0, getIncomingIndexFromAddress_1.default)(oldData.incoming, recipientAddress);
                        if (incomingIndex === -1) {
                            draft.incoming.push({
                                stream: null,
                                audio: null,
                                video: null,
                                address: recipientAddress,
                                status: retry
                                    ? types_1.VideoCallStatus.RETRY_INITIALIZED
                                    : types_1.VideoCallStatus.INITIALIZED,
                                retryCount: retry ? 1 : 0,
                            });
                        }
                        else {
                            draft.incoming[incomingIndex].address = recipientAddress;
                            draft.incoming[incomingIndex].status = retry
                                ? types_1.VideoCallStatus.RETRY_RECEIVED
                                : types_1.VideoCallStatus.RECEIVED;
                            draft.incoming[incomingIndex].retryCount += retry ? 1 : 0;
                        }
                    });
                });
                // setup error handler
                this.peerInstances[recipientAddress].on('error', (err) => {
                    if (this.data.incoming[0].retryCount >= 5) {
                        this.disconnect({ peerAddress: recipientAddress });
                    }
                    // retrying in case of connection error
                    (0, sendVideoCallNotification_1.default)({
                        signer: this.signer,
                        chainId: this.chainId,
                        pgpPrivateKey: this.pgpPrivateKey,
                    }, {
                        senderAddress,
                        recipientAddress,
                        status: types_1.VideoCallStatus.RETRY_INITIALIZED,
                        chatId,
                        rules,
                        signalData: null,
                        callType: this.callType,
                        env: this.env,
                    });
                });
                this.peerInstances[recipientAddress].signal(signalData);
                this.peerInstances[recipientAddress].on('signal', (data) => {
                    this.setData((oldData) => {
                        return (0, immer_1.produce)(oldData, (draft) => {
                            draft.meta.initiator.signal = data;
                        });
                    });
                    (0, sendVideoCallNotification_1.default)({
                        signer: this.signer,
                        chainId: this.chainId,
                        pgpPrivateKey: this.pgpPrivateKey,
                    }, {
                        senderAddress,
                        recipientAddress,
                        status: retry
                            ? types_1.VideoCallStatus.RETRY_RECEIVED
                            : types_1.VideoCallStatus.RECEIVED,
                        chatId,
                        rules,
                        signalData: data,
                        env: this.env,
                        callType: this.callType,
                        callDetails: details,
                    });
                });
                this.peerInstances[recipientAddress].on('connect', () => {
                    this.peerInstances[recipientAddress].send(JSON.stringify({
                        type: 'isVideoOn',
                        value: this.data.local.video,
                    }));
                    this.peerInstances[recipientAddress].send(JSON.stringify({
                        type: 'isAudioOn',
                        value: this.data.local.audio,
                    }));
                    // send the addresses the local peer is connected to remote peer
                    const connectedAddresses = (0, getConnectedAddresses_1.default)({
                        incomingPeers: this.data.incoming,
                    });
                    this.peerInstances[recipientAddress].send(JSON.stringify({
                        type: 'connectedAddresses',
                        value: connectedAddresses,
                    }));
                    // set videoCallInfo state with status connected for the receiver's end
                    this.setData((oldData) => {
                        return (0, immer_1.produce)(oldData, (draft) => {
                            const incomingIndex = (0, getIncomingIndexFromAddress_1.default)(oldData.incoming, recipientAddress);
                            draft.incoming[incomingIndex].status = types_1.VideoCallStatus.CONNECTED;
                        });
                    });
                });
                this.peerInstances[recipientAddress].on('data', (data) => {
                    var _a, _b, _c, _d, _e;
                    if ((0, isJSON_1.default)(data)) {
                        const parsedData = JSON.parse(data);
                        if (parsedData.type === 'connectedAddresses') {
                            const receivedConnectedAddresses = parsedData.value;
                            const localConnectedAddresses = (0, getConnectedAddresses_1.default)({
                                incomingPeers: this.data.incoming,
                            });
                            // find out the address to which local peer is not connected to but the remote peer is
                            // then connect with them
                            const connectToAddresses = (0, getConnectToAddresses_1.default)({
                                localAddress: senderAddress,
                                localConnectedAddresses,
                                receivedConnectedAddresses,
                            });
                            this.request({
                                senderAddress,
                                recipientAddress: connectToAddresses,
                                chatId,
                                rules,
                                details: {
                                    type: constants_2.SPACE_REQUEST_TYPE.ESTABLISH_MESH,
                                    data: {},
                                },
                            });
                        }
                        if (parsedData.type === 'isVideoOn') {
                            this.setData((oldData) => {
                                return (0, immer_1.produce)(oldData, (draft) => {
                                    const incomingIndex = (0, getIncomingIndexFromAddress_1.default)(oldData.incoming, recipientAddress);
                                    draft.incoming[incomingIndex].video = parsedData.value;
                                });
                            });
                        }
                        if (parsedData.type === 'isAudioOn') {
                            this.setData((oldData) => {
                                return (0, immer_1.produce)(oldData, (draft) => {
                                    const incomingIndex = (0, getIncomingIndexFromAddress_1.default)(oldData.incoming, recipientAddress);
                                    draft.incoming[incomingIndex].audio = parsedData.value;
                                });
                            });
                        }
                        if (parsedData.type === 'endCall') {
                            if (this.callType === constants_2.VIDEO_CALL_TYPE.PUSH_SPACE &&
                                ((_a = parsedData === null || parsedData === void 0 ? void 0 : parsedData.details) === null || _a === void 0 ? void 0 : _a.type) === constants_2.SPACE_DISCONNECT_TYPE.LEAVE) {
                                // destroy connection to only the current peer
                                (_b = this.peerInstances[recipientAddress]) === null || _b === void 0 ? void 0 : _b.destroy();
                                this.peerInstances[recipientAddress] = null;
                                this.setData((oldData) => {
                                    return (0, immer_1.produce)(oldData, (draft) => {
                                        const incomingIndex = (0, getIncomingIndexFromAddress_1.default)(oldData.incoming, recipientAddress);
                                        draft.incoming.splice(incomingIndex, 1);
                                    });
                                });
                            }
                            if (this.callType === constants_2.VIDEO_CALL_TYPE.PUSH_SPACE &&
                                ((_c = parsedData === null || parsedData === void 0 ? void 0 : parsedData.details) === null || _c === void 0 ? void 0 : _c.type) === constants_2.SPACE_DISCONNECT_TYPE.STOP) {
                                // destroy connection to all the peers
                                for (const connectedAddress in this.peerInstances) {
                                    (_d = this.peerInstances[connectedAddress]) === null || _d === void 0 ? void 0 : _d.destroy();
                                    this.peerInstances[connectedAddress] = null;
                                }
                                // destroy the local stream
                                if (this.data.local.stream) {
                                    (0, mediaToggle_1.endStream)(this.data.local.stream);
                                }
                                // reset the state
                                this.setData(() => exports.initVideoCallData);
                            }
                            if (this.callType === constants_2.VIDEO_CALL_TYPE.PUSH_VIDEO) {
                                (_e = this.peerInstances[recipientAddress]) === null || _e === void 0 ? void 0 : _e.destroy();
                                this.peerInstances[recipientAddress] = null;
                                // destroy the local stream
                                if (this.data.local.stream) {
                                    (0, mediaToggle_1.endStream)(this.data.local.stream);
                                }
                                // reset the state
                                this.setData(() => exports.initVideoCallData);
                            }
                        }
                    }
                    else if (onReceiveMessage) {
                        onReceiveMessage(data);
                    }
                });
                this.peerInstances[recipientAddress].on('stream', (currentStream) => {
                    const incomingIndex = (0, getIncomingIndexFromAddress_1.default)(this.data.incoming, recipientAddress);
                    this.onReceiveStream(currentStream, recipientAddress, this.data.incoming[incomingIndex].audio);
                    this.setData((oldData) => {
                        return (0, immer_1.produce)(oldData, (draft) => {
                            draft.incoming[incomingIndex].stream = currentStream;
                        });
                    });
                });
            }
            catch (err) {
                console.error('error in accept request', err);
            }
        });
    }
    connect(options) {
        var _a;
        const { peerAddress, signalData } = options || {};
        try {
            if (!peerAddress) {
                console.warn('disconnect requires a peer address');
            }
            // setup error handler
            this.peerInstances[peerAddress ? peerAddress : this.data.incoming[0].address].on('error', (err) => {
                const incomingIndex = peerAddress
                    ? (0, getIncomingIndexFromAddress_1.default)(this.data.incoming, peerAddress)
                    : 0;
                if (this.data.incoming[incomingIndex].retryCount >= 5) {
                    this.disconnect({
                        peerAddress: peerAddress
                            ? peerAddress
                            : this.data.incoming[0].address,
                    });
                }
                // retrying in case of connection error
                this.request({
                    senderAddress: this.data.local.address,
                    recipientAddress: this.data.incoming[incomingIndex].address,
                    chatId: this.data.meta.chatId,
                    retry: true,
                });
            });
            (_a = this.peerInstances[peerAddress ? peerAddress : this.data.incoming[0].address]) === null || _a === void 0 ? void 0 : _a.signal(signalData);
            // set videoCallInfo state with status connected for the caller's end
            this.setData((oldData) => {
                return (0, immer_1.produce)(oldData, (draft) => {
                    const incomingIndex = peerAddress
                        ? (0, getIncomingIndexFromAddress_1.default)(oldData.incoming, peerAddress)
                        : 0;
                    draft.incoming[incomingIndex].status = types_1.VideoCallStatus.CONNECTED;
                });
            });
        }
        catch (err) {
            console.error('error in connect', err);
        }
    }
    disconnect(options) {
        var _a, _b, _c;
        const { peerAddress, details } = options || {};
        try {
            if (!(options === null || options === void 0 ? void 0 : options.peerAddress)) {
                console.warn('disconnect requires a peer address');
            }
            const incomingIndex = peerAddress
                ? (0, getIncomingIndexFromAddress_1.default)(this.data.incoming, peerAddress)
                : 0;
            if (this.data.incoming[incomingIndex].status === types_1.VideoCallStatus.CONNECTED) {
                (_a = this.peerInstances[peerAddress ? peerAddress : this.data.incoming[0].address]) === null || _a === void 0 ? void 0 : _a.send(JSON.stringify({ type: 'endCall', value: true, details }));
                (_b = this.peerInstances[peerAddress ? peerAddress : this.data.incoming[0].address]) === null || _b === void 0 ? void 0 : _b.destroy();
            }
            else {
                // for disconnecting during status INITIALIZED, RECEIVED, RETRY_INITIALIZED, RETRY_RECEIVED
                // send a notif to the other user signaling status = DISCONNECTED
                (0, sendVideoCallNotification_1.default)({
                    signer: this.signer,
                    chainId: this.chainId,
                    pgpPrivateKey: this.pgpPrivateKey,
                }, {
                    senderAddress: this.data.local.address,
                    recipientAddress: this.data.incoming[incomingIndex].address,
                    status: types_1.VideoCallStatus.DISCONNECTED,
                    chatId: this.data.meta.chatId,
                    signalData: null,
                    env: this.env,
                    callType: this.callType,
                    callDetails: details,
                });
            }
            // destroy the peerInstance
            (_c = this.peerInstances[peerAddress ? peerAddress : this.data.incoming[0].address]) === null || _c === void 0 ? void 0 : _c.destroy();
            this.peerInstances[peerAddress ? peerAddress : this.data.incoming[0].address] = null;
            // destroy the local stream
            if (this.data.local.stream) {
                (0, mediaToggle_1.endStream)(this.data.local.stream);
            }
            // reset the state
            this.setData(() => exports.initVideoCallData);
        }
        catch (err) {
            console.error('error in disconnect', err);
        }
    }
    // functions for enabling/disabling local audio and video
    enableVideo(options) {
        var _a;
        const { state } = options || {};
        if (this.data.local.video !== state) {
            // need to change the video state
            // signal all the connected peers that the local peer has changed their video state
            for (const incomingPeer of this.data.incoming) {
                if (incomingPeer.status === types_1.VideoCallStatus.CONNECTED) {
                    (_a = this.peerInstances[incomingPeer.address]) === null || _a === void 0 ? void 0 : _a.send(JSON.stringify({
                        type: 'isVideoOn',
                        value: state,
                    }));
                }
            }
            if (this.data.local.stream) {
                if (state) {
                    (0, mediaToggle_1.restartVideoStream)(this.data.local.stream);
                }
                else {
                    (0, mediaToggle_1.stopVideoStream)(this.data.local.stream);
                }
                this.setData((oldData) => {
                    return (0, immer_1.produce)(oldData, (draft) => {
                        draft.local.video = state;
                    });
                });
            }
        }
    }
    enableAudio(options) {
        const { state } = options || {};
        if (this.data.local.audio !== state) {
            // need to change the audio state
            // Signal all the connected peers that the local peer has changed their audio state
            for (const incomingPeer of this.data.incoming) {
                if (incomingPeer.status === types_1.VideoCallStatus.CONNECTED &&
                    this.peerInstances[incomingPeer.address]) {
                    try {
                        this.peerInstances[incomingPeer.address].send(JSON.stringify({ type: 'isAudioOn', value: state }));
                    }
                    catch (error) {
                        console.error('Error sending data:', error);
                    }
                }
            }
            if (this.data.local.stream) {
                if (state) {
                    (0, mediaToggle_1.restartAudioStream)(this.data.local.stream);
                }
                else {
                    (0, mediaToggle_1.stopAudioStream)(this.data.local.stream);
                }
                this.setData((oldData) => {
                    return (0, immer_1.produce)(oldData, (draft) => {
                        draft.local.audio = state;
                    });
                });
            }
        }
    }
    // helper functions
    isInitiator() {
        if (this.data.meta.initiator.address === '' ||
            this.data.local.address === '')
            return false;
        return this.data.meta.initiator.address === this.data.local.address;
    }
}
exports.Video = Video;
//# sourceMappingURL=Video.js.map