const url = new URL(window.location);
/**
 * @type {import("./MWSE/index").default}
 */
let mwse;
/**
 * @type {string}
 */
let mySocketId;
/**
 * @type {string}
 */
let myIPAddress;
/**
 * @type {string}
 */
let myNumber;
/**
 * @type {string}
 */
let roomid;
/**
 * @type {import("./MWSE/Room").default}
 */
let room;
/**
 * @type {MediaStream}
 */
let outgoingStream;
/**
 * @type {HTMLDivElement}
 */
let videoContainer = document.querySelector(".videolist");
let maxbitrate;
let resulation;
let activePeers = {}
let ofscreencanvas = document.createElement("canvas");
function connect()
{
    mwse = new MWSE({
        endpoint: "wss://ws.saqut.com"
    });
    
    mwse.scope(beginEngine);
}
let peername = url.searchParams.get("user");
let interact = false;
setInterval(()=>{
    document.querySelectorAll(".soundon").forEach(e => (e.muted = 0,e.play()));
},1000)
document.addEventListener("click",()=>{
    interact = true;
    document.querySelectorAll(".soundon").forEach(e => (e.muted = 0,e.play()));
})
/**
 * @type {HTMLVideoElement}
 */
let activeVideo;
function templateVideo(name, stream,infinitedMute, peername)
{
    let t = new DOMParser().parseFromString(`
        
    `,"text/html");
    let i = t.querySelector("video");
    if(infinitedMute == true)
    {
        i.muted = 1;
    }else if(interact == false)
    {
        i.muted = 1;
        i.classList.add("soundon");
    }
    if(stream){
        i.srcObject = stream;
        bindAudioLevel(stream, t.querySelector(".progress-box"));
    }
    return t.querySelector("div");
}
function addVideoList(name, stream, peer, infinitedMute, name)
{
    if(!videoContainer.querySelector(`[name="${name}"]`))
    {
        let video = templateVideo(name, stream, infinitedMute, name);
        video.dataset.user = peer.socketId;
        videoContainer.appendChild(video);
    }
}
function removeVideoList(name)
{
    if(videoContainer.querySelector(`[data-user="${name}"]`))
    {
        let k = videoContainer.querySelector(`[data-user="${name}"]`);
        k.remove();
    }
}
async function beginEngine()
{
    let me = mwse.peer("me");
    me.disablePairAuth();
    mySocketId = me.socketId;
    myIPAddress = await mwse.virtualPressure.allocAPIPAddress();
    myNumber = await mwse.virtualPressure.allocAPNumber();
    roomid = url.searchParams.get("room");
    
    if(!!roomid == 0)
    {
        let hash = window.crypto.randomUUID();
        url.searchParams.set("room", hash);
        window.location = url.href;
    };
    connectRoom(roomid);
    
    if(url.searchParams.get("maxbitrate"))		
    {		
        let n = Number(url.searchParams.get("maxbitrate"));		
        if(Number.isFinite(n) && !Number.isNaN(n))		
        {		
            maxbitrate = n;		
        }else maxbitrate = 2500_000;
    }else maxbitrate = 2500_000;
    		
    if(url.searchParams.get("resulation"))		
    {		
        let n = Number(url.searchParams.get("resulation"));		
        if(Number.isFinite(n) && !Number.isNaN(n))		
        {		
            resulation = n;		
        }else resulation = 1.2;		
    }else resulation = 1.2;
};
window.addEventListener("load", () => {
    connect()
});
async function startOutgoingWebcam()
{
    let mediaStream = await navigator.mediaDevices.getUserMedia({
        video: /*true*/{
            advanced: [
                { width: { exact: 1920 } },
                { width: { exact: 1600 } },
                { width: { exact: 1366 } },
                { width: { exact: 1280 } },
                { width: { exact: 1024 } },
                { width: { exact: 900 } },
                { width: { exact: 800 } },
                { width: { exact: 640 } },
                { width: { exact: 320 } },
                { width: { exact: 240 } }
            ],
            facingMode: "user"
        },
        audio: true
    });
    outgoingStream = mediaStream;
}
async function connectRoom()
{
    await startOutgoingWebcam();
    room = mwse.room({
        name: roomid,
        joinType: "free",
        accessType: "private",
        description: "Private free joined room",
        ifexistsJoin: true,
        notifyActionEjected: true,
        notifyActionInvite: false,
        notifyActionJoined: true
    });
    await mwse.peer('me').info.set("name", peername);
    await room.createRoom();
    
    room.on("join", peer => IncomingPeer(peer, true));
    room.on("eject", peer => OutgoingPeer(peer));
    for (const peer of await room.fetchPeers()) {
        IncomingPeer(peer)
    }
    addVideoList("My Webcam",outgoingStream, mwse.peer("me"), true, peername);
};
/**
 * @param {import("./MWSE/Peer").default} peer 
 */
async function IncomingPeer(peer,activeConnect)
{
    await peer.info.fetch();
    
    peer.createRTC({
        iceCandidatePoolSize: 0
    },[{
        urls: "turn:20.166.82.187:3478",
        username: "turnserver",
        credential: "turnserver"
    },{
        urls: "stun:stun.l.google.com:19302"
    }]);
    if(activeConnect)
    {
        peer.rtc.connect();
    }
    peer.rtc.rtc.turboBitrate = 0;
    peer.rtc.on('connected',() => {
        if(!activeConnect)
        {
            peer.rtc.sendStream(outgoingStream, "Webcam", {});
        }
    });
    peer.rtc.on('disconnected',() => {
        removeVideoList(peer.socketId, peer);
        delete activePeers[peer.socketId];
    });
    peer.rtc.on("stream:added", ({stream,name}) => {
        addVideoList(
            peer.socketId,
            stream,
            peer,
            void 0,
            peer.info.get("name")
        );
        if(activeConnect)
        {
            peer.rtc.sendStream(outgoingStream, "Webcam", {});
        }
    })
}
/**
 * @param {import("./MWSE/Peer").default} peer 
 */
function OutgoingPeer(peer)
{
    removeVideoList(peer.socketId, peer);
    delete activePeers[peer.socketId];
}
let relative;
setInterval(() => {
    for(const [,peerRtc] of Object.entries(activePeers))
    {
        if(peerRtc?.turboBitrate !== 1)
        {
            const senders = peerRtc.getSenders();
            const videoSender = senders.find(sender => sender.track?.kind === 'video');
            if(videoSender){
                const parameters = videoSender.getParameters();
                parameters.encodings[0].maxBitrate = maxbitrate;
                parameters.encodings[0].scaleResolutionDownBy = resulation;
                videoSender.setParameters(parameters).then(() => {
                    peerRtc.turboBitrate = 1;
                });
            }
        }
    }
},1000);
function bindAudioLevel(stream, element, options = {}) {
    const {
        minPercent = 5,
        maxPercent = 100,
        decayRate = 0.97,    // 0.9–0.99 arasında önerilir
        volumeScale = 2.0   // gelen rms değerini büyütmek için (normalize daha geniş aralık)
    } = options;
    const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
    const source = audioCtx.createMediaStreamSource(stream);
    const analyser = audioCtx.createAnalyser();
    analyser.fftSize = 512;
    analyser.smoothingTimeConstant = 0.1;
    const dataArray = new Uint8Array(analyser.frequencyBinCount);
    source.connect(analyser);
    const track = stream.getAudioTracks()[0];
    const bufferLength = analyser.frequencyBinCount;
    function update()
    {
        if (track.readyState === 'ended' || !track.enabled) {
            source.disconnect();
            analyser.disconnect();
            audioCtx.close();
            return;
        }
        analyser.getByteFrequencyData(dataArray);
        // Ortalama ses seviyesi hesapla
        let sum = 0;
        for (let i = 0; i < bufferLength; i++) {
          sum += dataArray[i];
        }
        const avg = sum / bufferLength;
        // Ortalama değeri % olarak hesapla (0-255 arası değer)
        const volumePercent = Math.min(100, (avg / 255) * 100);
        element.style.width = `${volumePercent * 2}%`;
        requestAnimationFrame(update);
    }
    requestAnimationFrame(update);
}