"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
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());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MediaRoomProvider = exports.MediaRoomContext = void 0;
/* eslint-disable no-underscore-dangle */
const react_1 = __importStar(require("react"));
const react_redux_1 = require("react-redux");
const roomSlice_1 = require("../store/roomSlice");
const store_1 = require("../store/store");
const peersSlice_1 = require("../store/peersSlice");
const MediaRoomClient_1 = __importDefault(require("./context/MediaRoomClient"));
const MediaRoomSocketService_1 = require("./MediaRoomSocketService");
const participantSlice_1 = require("../store/participantSlice");
const UserTrackProvider_1 = require("./UserTrackProvider");
const analytics_1 = __importDefault(require("../utils/analytics"));
const ConfigProvider_1 = require("../utils/ConfigProvider");
const DyteMeeting_1 = require("../lib/DyteMeeting");
const BackgroundTimer_1 = __importDefault(require("../consolidatedLibraries/BackgroundTimer"));
const react_native_1 = require("react-native");
const logger_1 = __importDefault(require("../utils/logger"));
const { DyteHelper } = react_native_1.NativeModules;
exports.MediaRoomContext = react_1.createContext(null);
const MediaRoomProvider = ({ children, peerId, roomName, autoTune, }) => {
    const socketContext = react_1.useContext(MediaRoomSocketService_1.WebSocketContext);
    const { meeting, sessionConfig } = react_1.useContext(ConfigProvider_1.ConfigServiceContext);
    const { audio: audioAllowed } = sessionConfig.permissions.produce;
    const { mediaTracks: { webcamTrack, audioTrack }, inputDevices: { toggleVideoState }, } = react_1.useContext(UserTrackProvider_1.UserTrackContext);
    const dispatch = react_redux_1.useDispatch();
    const [instance, setInstance] = react_1.useState(null);
    const forceDisabledCamera = react_1.useRef(null);
    const instanceSave = react_1.useRef(null);
    const appState = react_1.useRef('');
    const interval = react_1.useRef(null);
    const socketState = react_redux_1.useSelector((state) => state.room.socketState);
    const producersState = react_redux_1.useSelector((state) => state.room.producersState);
    const videoProduction = react_redux_1.useSelector((state) => state.participant.videoProduction);
    const audioProduction = react_redux_1.useSelector((state) => state.participant.audioProduction);
    const audioMuted = react_redux_1.useSelector((state) => state.participant.audioMuted);
    react_1.useEffect(() => {
        if (instance) {
            instanceSave.current = instance;
        }
    }, [instance]);
    react_1.useEffect(() => {
        if (instance) {
            if (audioMuted) {
                // instance?.pauseMic();
                instance.muteSelf();
            }
            else {
                // instance?.resumeMic();
                instance.unmuteSelf();
            }
        }
    }, [audioMuted]);
    react_1.useEffect(() => {
        if (producersState === roomSlice_1.MediaStates.LOADED &&
            videoProduction === roomSlice_1.MediaStates.CONNECTING) {
            if (webcamTrack) {
                // eslint-disable-next-line no-unused-expressions
                instance === null || instance === void 0 ? void 0 : instance.shareWebcam(webcamTrack);
            }
            else {
                // eslint-disable-next-line no-unused-expressions
                instance === null || instance === void 0 ? void 0 : instance.disableWebcam();
            }
        }
    }, [webcamTrack, producersState]);
    react_1.useEffect(() => {
        if (producersState === roomSlice_1.MediaStates.LOADED &&
            audioProduction === roomSlice_1.MediaStates.CONNECTING) {
            if (audioTrack && audioAllowed && !audioMuted) {
                // eslint-disable-next-line no-unused-expressions
                instance === null || instance === void 0 ? void 0 : instance.shareMic(audioTrack);
            }
            else {
                // eslint-disable-next-line no-unused-expressions
                instance === null || instance === void 0 ? void 0 : instance.disableMic();
            }
        }
    }, [audioTrack, audioProduction]);
    react_1.useEffect(() => {
        const loadSignalling = (inst) => __awaiter(void 0, void 0, void 0, function* () {
            yield inst.getRoomState();
            yield inst.loadRouter();
            yield Promise.all([
                inst.createRecvTransport(),
                inst.createSendTransport(),
            ]);
            if (meeting) {
                meeting.sendRoomMessage = (message) => {
                    socketContext.sendMessage({
                        type: DyteMeeting_1.Events.roomMessage,
                        payload: Object.assign({}, message),
                    });
                };
                meeting.sendMessage = (peerId, message) => {
                    socketContext.sendMessage({
                        type: DyteMeeting_1.Events.message,
                        payload: {
                            peerId,
                            message,
                        },
                    });
                };
                meeting.kickAll = () => {
                    if (sessionConfig.permissions.kick_participant) {
                        inst.kickAll();
                    }
                };
                socketContext === null || socketContext === void 0 ? void 0 : socketContext.emitter.on('socket', (message) => meeting.onSocketMessage(message));
            }
            // TODO: Don't know why this was there?
            // if (joined) {
            // 	await inst.joinRoom(localStorage.getItem('self'));
            // }
            dispatch(roomSlice_1.setRouterFetchState(roomSlice_1.MediaStates.LOADED));
            dispatch(roomSlice_1.setProducersState(roomSlice_1.MediaStates.NOT_STARTED));
        });
        if (socketState === roomSlice_1.RoomSocketState.CONNECTED) {
            analytics_1.default.captureEvent('setting up connection', { peerId });
            if (meeting)
                meeting.emit(meeting.Events.connect);
            const newInstance = new MediaRoomClient_1.default(peerId, socketContext, dispatch, autoTune);
            setInstance(newInstance);
            loadSignalling(newInstance);
        }
        else if (socketState === roomSlice_1.RoomSocketState.DISCONNECTED) {
            analytics_1.default.captureEvent('socket disconnected', { peerId });
            instance === null || instance === void 0 ? void 0 : instance.stopAllTransports();
            socketContext === null || socketContext === void 0 ? void 0 : socketContext.emitter.removeAllListeners();
            dispatch(roomSlice_1.resetRoom({ roomName }));
            dispatch(peersSlice_1.resetPeers());
            dispatch(participantSlice_1.resetParticipant());
            setInstance(null);
            roomSlice_1.setRouterFetchState(roomSlice_1.MediaStates.NOT_APPLICABLE);
        }
    }, [socketState, peerId]);
    react_1.useEffect(() => () => {
        var _a, _b;
        (_a = instanceSave.current) === null || _a === void 0 ? void 0 : _a.stopAllProducers();
        (_b = instanceSave.current) === null || _b === void 0 ? void 0 : _b.stopAllTransports();
    }, []);
    const sendPing = () => {
        // fix this
        // socketContext.sendMessage({type: 'background-ping'});
    };
    const configureForeground = () => __awaiter(void 0, void 0, void 0, function* () {
        logger_1.default.trace('configureForeground');
        if (webcamTrack &&
            meeting.setupConfig.backgroundBehaviour === 'DISABLE_CAMERA_CAPTURE') {
            toggleVideoState();
            forceDisabledCamera.current = true;
        }
        if (react_native_1.Platform.Version >= 26) {
            yield DyteHelper.createNotificationChannel();
        }
        yield DyteHelper.startService();
    });
    const _handleAppStateChange = (nextAppState) => {
        if (appState.current.match(/inactive|background/) &&
            nextAppState === 'active') {
            logger_1.default.trace('configureBackground');
            BackgroundTimer_1.default.clearInterval(interval.current);
            interval.current = null;
            if (webcamTrack) {
                webcamTrack.enabled = false;
                setTimeout(() => {
                    if (webcamTrack) {
                        webcamTrack.enabled = true;
                    }
                }, 100);
            }
            if (forceDisabledCamera.current) {
                forceDisabledCamera.current = false;
                toggleVideoState();
            }
            // Problem is screensharing permission prompt makes the app state go in background
            // on permission prompt exit, the service is disabled which is required for screensharing
            if (!store_1.store.getState().room.screenShareRequested)
                DyteHelper.stopService();
        }
        else {
            if (interval.current === null) {
                configureForeground();
            }
            interval.current = BackgroundTimer_1.default.setInterval(() => sendPing(), 1000);
            appState.current = nextAppState;
        }
    };
    react_1.useEffect(() => {
        if (react_native_1.Platform.OS === 'android') {
            const appState = react_native_1.AppState.addEventListener('change', _handleAppStateChange);
            return () => {
                if (appState) {
                    appState.remove();
                }
                else {
                    react_native_1.AppState.removeEventListener('change', _handleAppStateChange);
                }
                if (interval.current)
                    BackgroundTimer_1.default.clearInterval(interval.current);
            };
        }
        return () => { };
    }, [webcamTrack, toggleVideoState]);
    const context = {
        mediaRoom: instance,
    };
    return (react_1.default.createElement(exports.MediaRoomContext.Provider, { value: context }, children));
};
exports.MediaRoomProvider = MediaRoomProvider;
//# sourceMappingURL=MediaRoomService.js.map