
// Warning: Please do not make any changes to this file.

var m_bActivatedChangeMedia = false;

function cVaxMediaWebRTC() 
{
    var m_hLocalAudioStream = null;

    var m_hLocalCameraStream = null;
    var m_hLocalScreenStream = null;

    var m_hProcMediaChanged = null;
    var m_hAudioMediaOut = null;
            
    //////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////

    this.ActivateMediaAudioInputWebRTC = async function (sDeviceId)
    {
        await ActivateMediaAudioInputWebRTC(sDeviceId);
    }
        
    //////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////

    this.ActivateCameraWebRTC = async function (sDeviceId)
    {
        let hVideoConstraints = AdjustCameraConstraints(sDeviceId);
        
        try
        {
            m_hLocalCameraStream = await navigator.mediaDevices.getUserMedia(hVideoConstraints);
        }
        catch (e)
        {
            m_hLocalCameraStream = null;
        }

        return m_hLocalCameraStream;
    }
            
    this.ActivateScreenWebRTC = async function ()
    {
        let hVideoConstraints = AdjustScreenConstraints();

        try
        {
            m_hLocalScreenStream = await navigator.mediaDevices.getDisplayMedia(hVideoConstraints);
        }
        catch (e)
        {
            m_hLocalScreenStream = null;
        }

        return m_hLocalScreenStream;
    }

    //////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////

    function AdjustCameraConstraints(sDeviceId)
    {
        let hVideoConstraints = null;

        if (sDeviceId === 'default' || sDeviceId === '')
        {
            hVideoConstraints =
            {
                video: true,
                audio: false
            };
        }
        else
        {
            hVideoConstraints =
            {
                video: { deviceId: { exact: sDeviceId } },
                audio: false
            };
        }

        return hVideoConstraints;
    }

    function AdjustScreenConstraints()
    {
        let hVideoConstraints = null;
            
        hVideoConstraints =
        {
            video: true,
            audio: false
        };
        
        return hVideoConstraints;
    }

    //////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////

    this.DeactivateMediaAudio = function ()
    {
        DeactivateMediaAudioWebRTC();
    }

    this.DeactivateMediaCamera = function ()
    {
        if (m_hLocalCameraStream == null)
            return;

        m_hLocalCameraStream.getTracks().forEach(function (track) { track.stop(); });
        m_hLocalCameraStream = null;
    }

    this.DeactivateMediaScreen = function ()
    {
        if (m_hLocalScreenStream == null)
            return;

        m_hLocalScreenStream.getTracks().forEach(function (track) { track.stop(); });
        m_hLocalScreenStream = null;
    }

    //////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////
        
    this.GetMediaAudioInputStream = function ()
    {
        return m_hLocalAudioStream;
    }

    //////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////
    
    this.OpenMediaAudioOutputWebRTC = async function (nDeviceNo, sDeviceId)
    {
        if (m_hAudioMediaOut == null)
        {
            m_hAudioMediaOut = new Array(2);

            m_hAudioMediaOut[0] = null;
            m_hAudioMediaOut[1] = null;
        }

        DestroyMediaAudioOutputWebRTC(nDeviceNo);

        m_hAudioMediaOut[nDeviceNo] = document.createElement("audio");
        m_hAudioMediaOut[nDeviceNo].autoplay = true;
        
        if (sDeviceId == 'default' || sDeviceId == '')
            return m_hAudioMediaOut[nDeviceNo];

        if (m_hAudioMediaOut[nDeviceNo].setSinkId)
        {
            await m_hAudioMediaOut[nDeviceNo].setSinkId(sDeviceId).catch((error) =>
            {
                console.error("Error setting output device: ", error);
            });
        }
        else
        {
            console.warn("setSinkId() is not supported in this browser.");
        }

        return m_hAudioMediaOut[nDeviceNo];
    }
        
    function DestroyMediaAudioOutputWebRTC(nDeviceNo)
    {
        if (m_hAudioMediaOut == null)
            return;

        if (m_hAudioMediaOut[nDeviceNo] == null)
            return;

        m_hAudioMediaOut[nDeviceNo].pause();
        m_hAudioMediaOut[nDeviceNo].autoplay = false;
        
        m_hAudioMediaOut[nDeviceNo] = null;
    }

    this.CloseMediaAudioOutputWebRTC = async function (nDeviceNo)
    {
        DestroyMediaAudioOutputWebRTC(nDeviceNo);
    }

    //////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////

    async function ActivateMediaAudioInputWebRTC(sDeviceId)
    {
        if (m_hLocalAudioStream)
        {
            m_hLocalAudioStream.getTracks().forEach(function (track) { track.stop(); });
            m_hLocalAudioStream = null;
        }
                        
        try
        {
            if (sDeviceId == 'default' || sDeviceId == '')
            {
                m_hLocalAudioStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: false });
            }
            else
            {
                m_hLocalAudioStream = await navigator.mediaDevices.getUserMedia({ audio: { deviceId: { exact: sDeviceId } }, video: false });
            }
        }
        catch (error)
        {
            m_hLocalAudioStream = null;
            console.error("Unable to capture media audio device: ", error);
        }
    }
       
    this.MuteMediaWebRTC = function(bMute)
    {
        if (m_hLocalAudioStream == null)
            return;
                
        m_hLocalAudioStream.getTracks().forEach(function (track) { track.enabled = !bMute; });
    }

    function DeactivateMediaAudioWebRTC()
    {
        m_bActivatedAudioMedia = false;
        m_bCapturedAudio = false;
                        
        if (m_hLocalAudioStream != null)
        {
            m_hLocalAudioStream.getTracks().forEach(function (track) { track.stop(); });
            m_hLocalAudioStream = null;
        }
                
        if (m_hAudioMediaOut != null)
        {
            DestroyMediaAudioOutputWebRTC(0);
            DestroyMediaAudioOutputWebRTC(1);

            m_hAudioMediaOut = null;
        }
    }
        
    //////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////

    async function ListAudioInputDevices(aListName, aListID, vDefault)
    {
        try
        {
            let hMedia = await navigator.mediaDevices.getUserMedia({ audio: true });

            const devices = await navigator.mediaDevices.enumerateDevices();
            const audioInputs = devices.filter(device => device.kind === "audioinput");

            hMedia.getTracks().forEach(track => track.stop());

            if (audioInputs.length == 0)
            {
                aListName.push('Default - Input Device');
                aListID.push('');

                vDefault.name = 'Default - Input Device';
                vDefault.id = '';

                return;
            }

            audioInputs.forEach(device =>
            {
                aListName.push(device.label);
                aListID.push(device.deviceId);
            });

            const defaultDevice = audioInputs.find(device => device.deviceId === "default");
                        
            if (defaultDevice)
            {
                vDefault.name = defaultDevice.label;
                vDefault.id = defaultDevice.deviceId;
            }
            else
            {
                vDefault.name = aListName[0];
                vDefault.id = aListID[0];
            }
        }
        catch (error)
        {
            console.error("Error accessing audio input devices: ", error);
        }
    }

    //////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////

    async function ListAudioOutputDevices(aListName, aListID, vDefault)
    {
        try
        {
            let hMedia = await navigator.mediaDevices.getUserMedia({ audio: true });

            const devices = await navigator.mediaDevices.enumerateDevices();
            const audioOutputs = devices.filter(device => device.kind === "audiooutput");

            hMedia.getTracks().forEach(track => track.stop());
                        
            if (audioOutputs.length == 0)
            {
                aListName.push('Default - Output Device');
                aListID.push('');

                vDefault.name = 'Default - Output Device';
                vDefault.id = '';

                return;
            }
                       
            audioOutputs.forEach(device =>
            {
                aListName.push(device.label);
                aListID.push(device.deviceId);
            });

            const defaultDevice = audioOutputs.find(device => device.deviceId === "default");

            if (defaultDevice)
            {
                vDefault.name = defaultDevice.label;
                vDefault.id = defaultDevice.deviceId;
            }
            else
            {
                vDefault.name = aListName[0];
                vDefault.id = aListID[0];
            }
        }
        catch (error)
        {
            console.error("Error accessing audio output devices: ", error);
        }
    }

    //////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////

    async function ListVideoDevices(aListName, aListID, vDefault)
    {
        try
        {
            let hMedia = await navigator.mediaDevices.getUserMedia({ video: true });

            const devices = await navigator.mediaDevices.enumerateDevices();
            const videoDevices = devices.filter(device => device.kind === "videoinput");

            if (videoDevices.length == 0)
            {
                aListName.push('Default - Video Device');
                aListID.push('');

                vDefault.name = 'Default - Video Device';
                vDefault.id = '';

                return;
            }

            hMedia.getTracks().forEach(track => track.stop());

            videoDevices.forEach(device =>
            {
                aListName.push(device.label);
                aListID.push(device.deviceId);
            });

            const defaultDevice = videoDevices.find(device => device.deviceId === "default");
                        
            if (defaultDevice)
            {
                vDefault.name = defaultDevice.label;
                vDefault.id = defaultDevice.deviceId;
            }
            else
            {
                vDefault.name = aListName[0];
                vDefault.id = aListID[0];
            }
        }
        catch (error)
        {
            console.error("Error accessing video devices: ", error);
        }
    }

    //////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////

    this.GetAudioInputDeviceList = async function (aListName, aListID, vDefault)
    {
        await ListAudioInputDevices(aListName, aListID, vDefault);
    }

    this.GetAudioOutputDeviceList = async function (aListName, aListID, vDefault)
    {
        await ListAudioOutputDevices(aListName, aListID, vDefault);
    }

    this.GetVideDeviceList = async function (aListName, aListID, vDefault)
    {
        await ListVideoDevices(aListName, aListID, vDefault);
    }

    this.ChangeAudioOutputDevice = async function (nDeviceNo, sDeviceId)
    {
        if (m_hAudioMediaOut[nDeviceNo] == null || sDeviceId == '')
            return;
                
        if (m_hAudioMediaOut[nDeviceNo].setSinkId)
        {
            await m_hAudioMediaOut[nDeviceNo].setSinkId(sDeviceId).catch((error) =>
            {
                console.error("Error changing output device: ", error);
            });
        }
        else
        {
            console.warn("setSinkId() is not supported in this browser.");
        }
    }

    //////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////

    this.AttachDetectMediaChange = function (hProcMediaChanged)
    {
        DetectChangeMedia();

        m_hProcMediaChanged = hProcMediaChanged;
    }

    function DetectChangeMedia()
    {
        if (m_bActivatedChangeMedia == true)
            return;
                
        m_bActivatedChangeMedia = true;

        navigator.mediaDevices.addEventListener('devicechange', OnChangeMediaDevices);
    }

    function OnChangeMediaDevices()
    {
        if (m_hProcMediaChanged == null)
            return;

        m_hProcMediaChanged();
    }

    //////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////

    this.PlayMediaStartFile = function (sDeviceId, sFileName, bLoop)
    {
        const hAudioElement = document.createElement("audio");

        hAudioElement.src = sFileName;

        hAudioElement.preload = "auto";
        hAudioElement.loop = bLoop;

        hAudioElement.play().catch(e => console.error("Playback error:", e));
                
        if (bLoop == false)
        {
            hAudioElement.addEventListener("ended", () =>
            {
                hAudioElement.pause();

                //hAudioElement.src = "";
                //hAudioElement = null;
            });
        }

        if (sDeviceId == 'default' || sDeviceId == '')
            return hAudioElement;

        if (hAudioElement.setSinkId)
        {
            hAudioElement.setSinkId(sDeviceId);
        }

        return hAudioElement;
    }

    this.PlayMediaStopFile = function (hAudio)
    {
        hAudio.pause();

        //hAudio.src = "";
        //hAudio.remove();

        //hAudio = null;
    }
}



/*
        navigator.mediaDevices.getUserMedia(hVideoConstraints)
        .then(OnMediaVideoSuccessWebRTC, OnMediaVideoFailedWebRTC)
        .catch(function (e)
        {
            m_bActivateVideo = false;
            m_hLocalVideoStream = null;
        });
        */


/*
        navigator.mediaDevices.getUserMedia({ audio: true, video: false })
        .then(OnMediaAudioSuccessWebRTC)
        .catch(function (e)
        {
            m_bActivatedMedia = false;
            m_bActivateAudio = false;
            m_hLocalAudioStream = null;

            ShowDialog('Unable to capture media audio device: ' + e.name);
        });
        */