/* eslint-disable no-underscore-dangle */
import React, { createContext, useContext, useState, useEffect, useRef, } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { MediaStates, setRouterFetchState, RoomSocketState, resetRoom, setProducersState, } from '../store/roomSlice';
import { store } from '../store/store';
import { resetPeers } from '../store/peersSlice';
import MediaRoomClient from '../services/context/MediaRoomClient';
import { WebSocketContext } from '../services/MediaRoomSocketService';
import { resetParticipant } from '../store/participantSlice';
import { UserTrackContext } from '../services/UserTrackProvider';
import analytics from '../utils/analytics';
import { ConfigServiceContext } from '../utils/ConfigProvider';
import { Events } from '../lib/DyteMeeting';
import BackgroundTimer from '../consolidatedLibraries/BackgroundTimer';
import { NativeModules, Platform, AppState } from 'react-native';
const { DyteHelper } = NativeModules;
export const MediaRoomContext = createContext(null);
export const MediaRoomProvider = ({ children, peerId, roomName, autoTune, }) => {
    const socketContext = useContext(WebSocketContext);
    const { meeting, sessionConfig } = useContext(ConfigServiceContext);
    const { audio: audioAllowed } = sessionConfig.permissions.produce;
    const { mediaTracks: { webcamTrack, audioTrack }, inputDevices: { toggleVideoState, }, } = useContext(UserTrackContext);
    const dispatch = useDispatch();
    const [instance, setInstance] = useState(null);
    const forceDisabledCamera = useRef(null);
    const instanceSave = useRef(null);
    const appState = useRef('');
    const interval = useRef(null);
    const socketState = useSelector((state) => state.room.socketState);
    const producersState = useSelector((state) => state.room.producersState);
    const videoProduction = useSelector((state) => state.participant.videoProduction);
    const audioProduction = useSelector((state) => state.participant.audioProduction);
    const audioMuted = useSelector((state) => state.participant.audioMuted);
    useEffect(() => {
        if (instance) {
            instanceSave.current = instance;
        }
    }, [instance]);
    useEffect(() => {
        if (instance) {
            if (audioMuted) {
                // instance?.pauseMic();
                instance.muteSelf();
            }
            else {
                // instance?.resumeMic();
                instance.unmuteSelf();
            }
        }
    }, [audioMuted]);
    useEffect(() => {
        if (producersState === MediaStates.LOADED
            && videoProduction === MediaStates.CONNECTING) {
            if (webcamTrack) {
                // eslint-disable-next-line no-unused-expressions
                instance?.shareWebcam(webcamTrack);
            }
            else {
                // eslint-disable-next-line no-unused-expressions
                instance?.disableWebcam();
            }
        }
    }, [webcamTrack, producersState]);
    useEffect(() => {
        if (producersState === MediaStates.LOADED
            && audioProduction === MediaStates.CONNECTING) {
            if (audioTrack && audioAllowed && !audioMuted) {
                // eslint-disable-next-line no-unused-expressions
                instance?.shareMic(audioTrack);
            }
            else {
                // eslint-disable-next-line no-unused-expressions
                instance?.disableMic();
            }
        }
    }, [audioTrack, audioProduction]);
    useEffect(() => {
        const loadSignalling = async (inst) => {
            await inst.getRoomState();
            await inst.loadRouter();
            await Promise.all([
                inst.createRecvTransport(),
                inst.createSendTransport(),
            ]);
            if (meeting) {
                meeting.sendRoomMessage = (message) => {
                    socketContext.sendMessage({
                        type: Events.roomMessage,
                        payload: {
                            message,
                        },
                    });
                };
                meeting.sendMessage = (peerId, message) => {
                    socketContext.sendMessage({
                        type: Events.message,
                        payload: {
                            peerId,
                            message,
                        },
                    });
                };
                meeting.kickAll = () => {
                    if (sessionConfig.permissions.kick_participant) {
                        inst.kickAll();
                    }
                };
                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(setRouterFetchState(MediaStates.LOADED));
            dispatch(setProducersState(MediaStates.NOT_STARTED));
        };
        if (socketState === RoomSocketState.CONNECTED) {
            analytics.captureEvent('setting up connection', { peerId });
            if (meeting)
                meeting.emit(meeting.Events.connect);
            const newInstance = new MediaRoomClient(peerId, socketContext, dispatch, autoTune);
            setInstance(newInstance);
            loadSignalling(newInstance);
        }
        else if (socketState === RoomSocketState.DISCONNECTED) {
            analytics.captureEvent('socket disconnected', { peerId });
            instance?.stopAllTransports();
            socketContext?.emitter.removeAllListeners();
            dispatch(resetRoom({ roomName }));
            dispatch(resetPeers());
            dispatch(resetParticipant());
            setInstance(null);
            setRouterFetchState(MediaStates.NOT_APPLICABLE);
        }
    }, [socketState, peerId]);
    useEffect(() => () => {
        instanceSave.current?.stopAllProducers();
        instanceSave.current?.stopAllTransports();
    }, []);
    const sendPing = () => {
        // fix this
        // socketContext.sendMessage({type: 'background-ping'});
    };
    const configureForeground = async () => {
        if (webcamTrack && meeting.setupConfig.backgroundBehaviour === 'DISABLE_CAMERA_CAPTURE') {
            toggleVideoState();
            forceDisabledCamera.current = true;
        }
        if (Platform.Version >= 26) {
            await DyteHelper.createNotificationChannel();
        }
        await DyteHelper.startService();
    };
    const _handleAppStateChange = (nextAppState) => {
        if (appState.current.match(/inactive|background/)
            && nextAppState === 'active') {
            BackgroundTimer.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.getState().room.screenShareRequested)
                DyteHelper.stopService();
        }
        else {
            if (interval.current === null) {
                configureForeground();
            }
            interval.current = BackgroundTimer.setInterval(() => sendPing(), 1000);
            appState.current = nextAppState;
        }
    };
    useEffect(() => {
        if (Platform.OS === 'android') {
            const appState = AppState.addEventListener('change', _handleAppStateChange);
            return () => {
                if (appState) {
                    appState.remove();
                }
                else {
                    AppState.removeEventListener('change', _handleAppStateChange);
                }
                if (interval.current)
                    BackgroundTimer.clearInterval(interval.current);
            };
        }
        return () => { };
    }, [webcamTrack, toggleVideoState]);
    const context = {
        mediaRoom: instance,
    };
    return (<MediaRoomContext.Provider value={context}>
			{children}
		</MediaRoomContext.Provider>);
};
//# sourceMappingURL=MediaRoomService.js.map