package com.avairebot.scheduler;

import com.avairebot.AvaIre;
import com.avairebot.audio.AudioHandler;
import com.avairebot.audio.GuildMusicManager;
import com.avairebot.contracts.scheduler.Job;
import com.avairebot.factories.MessageFactory;
import net.dv8tion.jda.core.entities.Member;
import net.dv8tion.jda.core.entities.VoiceChannel;
import net.dv8tion.jda.core.managers.AudioManager;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.TimeUnit;

public class MusicActivityJob extends Job {

    public final static Map<Long, Integer> MISSING_LISTENERS = new HashMap<>();
    public final static Map<Long, Integer> EMPTY_QUEUE = new HashMap<>();

    public MusicActivityJob(AvaIre avaire) {
        super(avaire, 30, 30, TimeUnit.SECONDS);
    }

    @Override
    public void run() {
        Iterator<AudioManager> iterator = avaire.getShards().get(0).getJDA().getAudioManagers().iterator();

        try {
            while (iterator.hasNext()) {
                AudioManager manager = iterator.next();

                if (!manager.isConnected()) {
                    continue;
                }

                long guildId = manager.getGuild().getIdLong();

                if (!AudioHandler.MUSIC_MANAGER.containsKey(guildId)) {
                    handleEmptyMusic(manager, null, guildId);
                    continue;
                }

                GuildMusicManager guildMusicManager = AudioHandler.MUSIC_MANAGER.get(guildId);

                if (guildMusicManager.getScheduler().getQueue().isEmpty() && guildMusicManager.getPlayer().getPlayingTrack() == null) {
                    handleEmptyMusic(manager, guildMusicManager, guildId);
                    continue;
                }

                if (EMPTY_QUEUE.containsKey(guildId)) {
                    EMPTY_QUEUE.remove(guildId);
                }

                VoiceChannel voiceChannel = manager.getConnectedChannel();

                boolean hasListeners = false;
                for (Member member : voiceChannel.getMembers()) {
                    if (member.getUser().isBot()) {
                        continue;
                    }

                    if (member.getVoiceState().isDeafened()) {
                        continue;
                    }

                    hasListeners = true;
                    break;
                }

                if (hasListeners && !manager.getGuild().getSelfMember().getVoiceState().isMuted()) {
                    MISSING_LISTENERS.remove(guildId);
                    continue;
                }

                int times = MISSING_LISTENERS.getOrDefault(guildId, 0) + 1;

                if (times <= 6) {
                    MISSING_LISTENERS.put(guildId, times);
                    continue;
                }

                clearItems(manager, guildMusicManager, guildId);
            }
        } catch (Exception e) {
            AvaIre.getLogger().error("An exception occurred during music activity job: " + e.getMessage(), e);
        }
    }

    private void handleEmptyMusic(AudioManager manager, GuildMusicManager guildMusicManager, long guildId) {
        int times = EMPTY_QUEUE.getOrDefault(guildId, 0) + 1;

        if (times <= 4) {
            EMPTY_QUEUE.put(guildId, times);
            return;
        }

        clearItems(manager, guildMusicManager, guildId);
    }

    private void clearItems(AudioManager manager, GuildMusicManager guildMusicManager, long guildId) {
        if (guildMusicManager != null) {
            guildMusicManager.getScheduler().getQueue().clear();
            guildMusicManager.getPlayer().destroy();

            if (guildMusicManager.getLastActiveMessage() != null) {
                MessageFactory.makeInfo(guildMusicManager.getLastActiveMessage(), "The music has ended due to inactivity.").queue();
            }
        }

        AudioHandler.MUSIC_MANAGER.remove(guildId);
        MISSING_LISTENERS.remove(guildId);
        EMPTY_QUEUE.remove(guildId);

        manager.closeAudioConnection();
    }
}

@@ -696,16 +696,92 @@
 Map%3C%3E();
+%0A    public final static Map%3CLong, Integer%3E PLAYER_PAUSED = new HashMap%3C%3E();
 %0A%0A    pu
@@ -1948,32 +1948,221 @@
              %7D%0A%0A
+                if (guildMusicManager.getPlayer().isPaused()) %7B%0A                    handlePausedMusic(manager, guildMusicManager, guildId);%0A                    continue;%0A                %7D%0A%0A
                 
@@ -3642,32 +3642,376 @@
 uildId);%0A    %7D%0A%0A
+    private void handlePausedMusic(AudioManager manager, GuildMusicManager guildMusicManager, long guildId) %7B%0A        int times = PLAYER_PAUSED.getOrDefault(guildId, 0) + 1;%0A%0A        if (times %3C= 20) %7B%0A            PLAYER_PAUSED.put(guildId, times);%0A            return;%0A        %7D%0A%0A        clearItems(manager, guildMusicManager, guildId);%0A    %7D%0A%0A
     private void
@@ -4527,32 +4527,32 @@
 emove(guildId);%0A
-
         MISSING_
@@ -4570,32 +4570,71 @@
 emove(guildId);%0A
+        PLAYER_PAUSED.remove(guildId);%0A
         EMPTY_QU

Add auto disconnect on inactivity if music is paused