/*
 * Copyright 2021 John Grosh <john.a.grosh@gmail.com>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.jagrosh.jmusicbot.audio;

import com.jagrosh.jmusicbot.Bot;
import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.events.guild.voice.GuildVoiceUpdateEvent;

import java.time.Instant;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 *
 * @author Michaili K (mysteriouscursor+git@protonmail.com)
 */
public class AloneInVoiceHandler
{
    private final Bot bot;
    private final HashMap<Guild, Instant> aloneSince = new HashMap<>();
    private long aloneTimeUntilStop = 0;

    public AloneInVoiceHandler(Bot bot)
    {
        this.bot = bot;
    }
    
    public void init()
    {
        aloneTimeUntilStop = bot.getConfig().getAloneTimeUntilStop();
        if(aloneTimeUntilStop > 0)
            bot.getThreadpool().scheduleWithFixedDelay(() -> check(), 0, 5, TimeUnit.SECONDS);
    }
    
    private void check()
    {
        Set<Guild> toRemove = new HashSet<>();
        for(Map.Entry<Guild, Instant> entrySet: aloneSince.entrySet())
        {
            if(entrySet.getValue().getEpochSecond() > Instant.now().getEpochSecond()- aloneTimeUntilStop) continue;

            ((AudioHandler) entrySet.getKey().getAudioManager().getSendingHandler()).stopAndClear();
            entrySet.getKey().getAudioManager().closeAudioConnection();

            toRemove.add(entrySet.getKey());
        }
        toRemove.forEach(id -> aloneSince.remove(id));
    }

    public void onVoiceUpdate(GuildVoiceUpdateEvent event)
    {
        if(aloneTimeUntilStop <= 0) return;

        Guild guild = event.getEntity().getGuild();
        if(!bot.getPlayerManager().hasHandler(guild)) return;

        boolean alone = isAlone(guild);
        boolean inList = aloneSince.containsKey(guild);

        if(!alone && inList)
            aloneSince.remove(guild);
        else if(alone && !inList)
            aloneSince.put(guild, Instant.now());
    }

    private boolean isAlone(Guild guild)
    {
        if(guild.getAudioManager().getConnectedChannel() == null) return false;
        return guild.getAudioManager().getConnectedChannel().getMembers().stream()
                .noneMatch(x ->
                        !x.getVoiceState().isDeafened()
                        && x.getIdLong() != bot.getJDA().getSelfUser().getIdLong());
    }
}

@@ -722,17 +722,21 @@
 ntities.
-*
+Guild
 ;%0Aimport
@@ -1119,21 +1119,20 @@
 HashMap%3C
-Guild
+Long
 , Instan
@@ -1570,21 +1570,20 @@
     Set%3C
-Guild
+Long
 %3E toRemo
@@ -1626,21 +1626,20 @@
 p.Entry%3C
-Guild
+Long
 , Instan
@@ -1768,16 +1768,17 @@
 Second()
+ 
 - aloneT
@@ -1818,41 +1818,236 @@
     
-((AudioHandler) entrySet.getKey()
+Guild guild = bot.getJDA().getGuildById(entrySet.getKey());%0A%0A            if(guild == null)%0A            %7B%0A                toRemove.add(entrySet.getKey());%0A                continue;%0A            %7D%0A%0A            ((AudioHandler) guild
 .get
@@ -2110,33 +2110,21 @@
         
-entrySet.getKey()
+guild
 .getAudi
@@ -2594,16 +2594,28 @@
 ey(guild
+.getIdLong()
 );%0A%0A    
@@ -2670,24 +2670,36 @@
 remove(guild
+.getIdLong()
 );%0A        e
@@ -2755,16 +2755,28 @@
 ut(guild
+.getIdLong()
 , Instan

Store guild ID instead of the guild object in AloneInVoiceHandler