import { mediaDevices } from 'react-native-webrtc';
import { getHeadset, addListener as bluetoothListener } from '../consolidatedLibraries/BluetoothHeadsetDetect';
import { NativeEventEmitter, NativeModules } from 'react-native';
import { HD_QUALITY_PEERS_LIMIT, VIDEO_CONSTRAINS, VIDEO_CONSTRAINS_SCREENSHARE } from '../RoomConfig';
const masterOut = NativeModules.InCallManager;
const masterOutEmitter = new NativeEventEmitter(masterOut);
export const getAllMediaDevices = async () => {
    const devices = await mediaDevices.enumerateDevices();
    return devices;
};
// Get All audio device should emit all audio device and whenever device changes
// Initially we will have default audio as phone microphone
// then we will have listener for bluetooth and wiredheadset which will emit code upwards
// Event listener code
export class AudioDevicesEmitter {
    constructor(callback) {
        if (!callback) {
            throw new Error('Callback not initalized');
        }
        this.callback = callback;
        // Not doing anything with haveMic for now
        this.notConnected = {
            connected: false,
            haveMic: false,
        };
        this.connectedWithMic = {
            connected: true,
            haveMic: true,
        };
        this.connectedWithoutMic = {
            connected: true,
            haveMic: false,
        };
        const bluetoothDeviceConnected = getHeadset();
        this.audioDevices = {
            speaker: this.connectedWithMic,
            bluetooth: bluetoothDeviceConnected ? this.connectedWithMic : this.notConnected,
            wired: this.notConnected,
        };
        this.onBluetoothEvent();
        this.onWiredHeadsetEvent();
        this.emit();
        this.wiredHeadListener = null;
    }
    onBluetoothEvent() {
        bluetoothListener((bluetoothDevice) => {
            const { connected } = this.audioDevices.bluetooth;
            // TODO: Setting haveMic default to true because
            // bluetooth package does not detect if wireless device have mic or not
            if (bluetoothDevice && !connected) {
                this.audioDevices = {
                    ...this.audioDevices,
                    bluetooth: { ...this.connectedWithMic },
                };
                this.emit();
            }
            else if (!bluetoothDevice && connected) {
                this.audioDevices = {
                    ...this.audioDevices,
                    bluetooth: { ...this.notConnected },
                };
                this.emit();
            }
        });
    }
    onWiredHeadsetEvent() {
        this.wiredHeadListener = masterOutEmitter.addListener('WiredHeadset', (data) => {
            if (data) {
                const { isPlugged, hasMic } = data;
                const { connected } = this.audioDevices.wired;
                if (isPlugged && !connected) {
                    const wired = hasMic ? { ...this.connectedWithMic } : { ...this.connectedWithoutMic };
                    this.audioDevices = {
                        ...this.audioDevices,
                        wired,
                    };
                    this.emit();
                }
                else if (!isPlugged && connected) {
                    this.audioDevices = {
                        ...this.audioDevices,
                        wired: { ...this.notConnected },
                    };
                    this.emit();
                }
            }
        });
    }
    getAudioDevices() {
        return this.formatAudioDevices();
    }
    formatAudioDevices() {
        return Object.keys(this.audioDevices).map((audioDevice) => {
            const audioDeviceProps = this.audioDevices[audioDevice];
            return {
                ...audioDeviceProps, deviceId: audioDevice, label: audioDevice, kind: 'audioinput',
            };
        }).filter((audioDevice) => audioDevice.connected);
    }
    emit() {
        this.callback(this.formatAudioDevices());
    }
    removeListener() {
        this.wiredHeadListener?.remove();
    }
}
// Samsung devices gives multiple front and back video camera
// Log 1: https://sentry.io/organizations/dyte-in/issues/2654518025/events/9035bfb550fa4de7b3aa698534edd7da/?environment=production&project=5766483
// Log 2: https://sentry.io/organizations/dyte-in/issues/2654518025/events/748b9a99288d4845bde888a7ea925622/?environment=production&project=5766483
export const getAllVideoDevices = async () => {
    const deviceMem = {};
    const devices = await getAllMediaDevices();
    return devices.filter((d) => {
        if (d.kind === 'videoinput' && !deviceMem[d.facing]) {
            deviceMem[d.facing] = true;
            return d;
        }
        return false;
    });
};
export const getWebcamConstraints = (quality, frameRate) => {
    const constraints = VIDEO_CONSTRAINS[quality.toLowerCase()];
    if (!constraints) {
        throw new Error('Invalid quality');
    }
    if (frameRate) {
        if (frameRate < 5 || frameRate > 30) {
            throw new Error('Invalid framerate');
        }
        constraints.frameRate = { ideal: frameRate };
    }
    return constraints;
};
export const getScreenShareConstraints = (quality, frameRate) => {
    const constraints = VIDEO_CONSTRAINS_SCREENSHARE[quality.toLowerCase() || 'vga'];
    if (!constraints) {
        throw new Error('Invalid quality');
    }
    if (frameRate) {
        if (frameRate < 5 || frameRate > 30) {
            throw new Error('Invalid framerate');
        }
        constraints.frameRate = { max: frameRate };
    }
    return constraints;
};
export const getVideoTrack = async (deviceId, quality) => {
    const qual = quality || VIDEO_CONSTRAINS.vga;
    const stream = await mediaDevices.getUserMedia({
        video: {
            deviceId: deviceId || '',
            frameRate: 24,
            ...qual,
        },
        audio: false,
    });
    return stream.getVideoTracks()[0];
};
export const getAudioTrack = async () => {
    const stream = await mediaDevices.getUserMedia({
        audio: true,
        video: false,
    });
    return stream.getAudioTracks()[0];
};
export const getSpeakerTrack = async (deviceId) => {
    const advanced = {};
    // const stream = await mediaDevices.getUserMedia(
    // 	{
    // 		audio:
    // 		{
    // 			deviceId: { ideal: deviceId || '' },
    // 			...advanced,
    // 		},
    // 		video: false,
    // 	},
    // );
    return null;
};
export const getScreenShare = async () => {
    // @ts-ignore
    const stream = await mediaDevices.getDisplayMedia({
        audio: true,
        video: {
            displaySurface: 'monitor',
            logicalSurface: true,
            cursor: true,
            width: { max: 1920 },
            height: { max: 1080 },
            frameRate: { max: 5 },
        },
    });
    return { video: stream.getTracks()[0], audio: null };
};
export const setOnDeviceChange = (callback) => {
    /* mediaDevices.ondevicechange = () => {
        callback();
    }; */
};
export const getQualityAfterLegacyModeShift = (isLegacy, joinedPeersLength, previousVideoQuality) => {
    if (joinedPeersLength === HD_QUALITY_PEERS_LIMIT && isLegacy) {
        return VIDEO_CONSTRAINS.vga;
    }
    if (joinedPeersLength === HD_QUALITY_PEERS_LIMIT + 1 && !isLegacy) {
        return VIDEO_CONSTRAINS.hd;
    }
    return previousVideoQuality;
};
//# sourceMappingURL=media-utils.js.map