const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));

const volume = parseInt((new URLSearchParams(window.location.search)).get('vol')) || 100

$(async function () {
    const webSocket = window.socket;
    const announceQueue = [];

    const playAudio = (src) =>{
        return new Promise(resolve =>{
            var audio = new Audio();
            $(audio).on("loadedmetadata", function() {
                resolve(audio);
            });
            audio.volume = Math.min(1,Math.max(0,volume/100.0));
            audio.src = src;
            audio.play().catch((err)=>{
                if(err.toString().startsWith('NotAllowedError')){
                    $('body').append($('<button/>', {
                        'html': 'Enable Audio Hook',
                        'style': 'top:80%;left:50%; position: absolute; font-size: 30px; transform: translateX(-50%) translateY(-50%);'
                    }).on('click', function(){$(this).remove()}));
                }
            });
        });
      }


    const renderEl = async (pic, music, message, detail) => {
        let node = document.getElementById('main');
        let nodeIm = document.getElementById('img');
        node.innerHTML = message;
        nodeIm.src = pic
        let audio = await playAudio(music);
        node.style.opacity = 1;
        nodeIm.style.opacity = 1;
        await sleep(Math.max(audio.duration*1000 - 1000,4000));
        node.style.opacity = 0;
        nodeIm.style.opacity = 0;
    }
    
    const renderStart = async (an) => {
        await renderEl('','./media/sonar.ogg',
                       `The Stream Started`, `...`)
    }

    const renderFollow = async (an) => {
        await renderEl('./media/donate.gif','./media/sonar.ogg',
                       `${an.user} joined the squad !`, `...`)
    }

    const renderSubscribe = async (an) => {
        // TTS: an.details.message
        let v = an.details.isReSub ? 'resubscribed' : 'subscribed'
        let detail = an.details.months == 0 ? '' : `for ${an.details.months} months `
        let message = `${an.user} ${v} ${detail}!`
        await renderEl('./media/follow.gif','./media/follow.mp3',
        message,
        `...`)
    }

    const renderGift = async (an) => {
        await renderEl('./media/follow.gif','./media/follow.mp3',
        `${an.user} gifted ${an.details.recipient} a sub !`,
        `...`)
    }

    const renderMassGift = async (an) => {
        await renderEl('./media/follow.gif','./media/follow.mp3',
        `${an.user} gifted ${an.details.amount} subs to the community !`,
        `...`)
    }

    const renderRaid = async (an) => {
        await renderEl('./media/raid.gif','./media/subscribe.mp3',
        `${an.user} is Raiding with a party of ${an.details.viewers} !`,
        `...`)
    }

    const renderBits = async (an) => {
        // TTS: an.details.message
        await renderEl('','',
        `${an.user} cheered ${an.details.amount} bitties!`,
        `...`)
    }

    const renderAnnouncement = async (an) => {
        if(an.tpe=='follow') await renderFollow(an)
        else if(an.tpe=='subscribe') await renderSubscribe(an)
        else if(an.tpe=='gift') await renderGift(an)
        else if(an.tpe=='mgift') await renderMassGift(an)
        else if(an.tpe=='raid') await renderRaid(an)
        else if(an.tpe=='bits') await renderBits(an)
        else if(an.tpe=='start') await renderStart(an)
    }

    class Announcement {
        constructor(data){
            this.user = data.user;
            this.tpe = data.tpe || 'start';
            this.details = data.details || {};
        }
    }


    announceQueue.push(new Announcement({user:"-",tpe:"start"}));
    const main = async () => {
        while(true){
            if(announceQueue.length>0)
                await renderAnnouncement(announceQueue.shift());
            await sleep(1000);
        }
    }
    main();

    const handleSocketMessage = async (e)=>{
        try {
            let rawMessage = e.data,
                message = JSON.parse(rawMessage);

            if(!message.hasOwnProperty('eventFamily') || message.eventFamily != 'calert' || 
                !message.hasOwnProperty('eventType') || !message.hasOwnProperty('data'))
                return;
            if(message.eventType == 'follow') {
                announceQueue.push(new Announcement({user:message.data.user, tpe:'follow'}))
            }else if(message.eventType == 'subscribe') {
                announceQueue.push(new Announcement({user:message.data.user, tpe:'subscribe', details:message.data.details}))
            }else if(message.eventType == 'gift') {
                announceQueue.push(new Announcement({user:message.data.user, tpe:'gift', details:message.data.details}))
            }else if(message.eventType == 'mgift') {
                announceQueue.push(new Announcement({user:message.data.user, tpe:'mgift', details:message.data.details}))
            }else if(message.eventType == 'raid') {
                announceQueue.push(new Announcement({user:message.data.user, tpe:'raid', details:message.data.details}))
            }else if(message.eventType == 'bits') {
                announceQueue.push(new Announcement({user:message.data.user, tpe:'bits'}))
            }else{
                console.log("unhandled:", message.eventType)
            }
        } catch (ex) {
            console.log(ex)
        }
    };


    jQuery(async ()=>{
        
        try{
            socket.addFamilyHandler("calert", handleSocketMessage);
            if(socket){
                while(socket.getReadyState() === 0){
                    await new Promise(r => setTimeout(r, 500));
                }
            }
        }catch(e) {console.log(e)}
    })

});