package com.avairebot.orion.audio;

import com.avairebot.orion.factories.MessageFactory;
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers;
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import net.dv8tion.jda.core.entities.Guild;
import net.dv8tion.jda.core.entities.Message;
import net.dv8tion.jda.core.entities.VoiceChannel;
import net.dv8tion.jda.core.managers.AudioManager;

import java.util.HashMap;
import java.util.Map;

public class AudioHandler {

    private static final AudioPlayerManager AUDIO_PLAYER_MANAGER;
    private static final Map<Long, GuildMusicManager> MUSIC_MANAGER;

    static {
        MUSIC_MANAGER = new HashMap<>();
        AUDIO_PLAYER_MANAGER = new DefaultAudioPlayerManager();

        AudioSourceManagers.registerRemoteSources(AUDIO_PLAYER_MANAGER);
        AudioSourceManagers.registerLocalSource(AUDIO_PLAYER_MANAGER);
    }

    public static void loadAndPlay(final Message message, final String trackUrl) {
        GuildMusicManager musicManager = getGuildAudioPlayer(message.getGuild());

        musicManager.setLastActiveMessage(message);

        AUDIO_PLAYER_MANAGER.loadItemOrdered(musicManager, trackUrl, new AudioLoadResultHandler() {
            @Override
            public void trackLoaded(AudioTrack track) {
                if (musicManager.getPlayer().getPlayingTrack() != null) {
                    MessageFactory.makeSuccess(message, "<@%s> has added [%s](%s) to the queue. There are `%s` song(s) ahead of it in the queue.",
                            message.getAuthor().getId(),
                            track.getInfo().title,
                            track.getInfo().uri,
                            getQueueSize(musicManager)
                    ).queue();
                }

                play(message, musicManager, track);
            }

            @Override
            public void playlistLoaded(AudioPlaylist playlist) {
                MessageFactory.makeSuccess(message, "<@%s> has added %s songs from the [%s](%s) playlist to the queue. There are `%s` song(s) ahead of it in the queue.",
                        message.getAuthor().getId(),
                        playlist.getTracks().size(),
                        playlist.getName(),
                        trackUrl,
                        getQueueSize(musicManager)
                ).queue();

                for (AudioTrack track : playlist.getTracks()) {
                    play(message, musicManager, track);
                }
            }

            @Override
            public void noMatches() {
                MessageFactory.makeWarning(message, "I found nothing with the given query `%s`", trackUrl).queue();
            }

            @Override
            public void loadFailed(FriendlyException exception) {
                MessageFactory.makeError(message, "I couldn't add that to the queue: %s", exception.getMessage()).queue();
            }
        });
    }

    public static void skipTrack(Message message) {
        GuildMusicManager musicManager = getGuildAudioPlayer(message.getGuild());
        musicManager.scheduler.nextTrack();
    }

    private static void play(Message message, GuildMusicManager musicManager, AudioTrack track) {
        connectToFirstVoiceChannel(message.getGuild().getAudioManager());

        musicManager.scheduler.queue(track, message.getAuthor());
    }

    private static void connectToFirstVoiceChannel(AudioManager audioManager) {
        if (!audioManager.isConnected() && !audioManager.isAttemptingToConnect()) {
            for (VoiceChannel voiceChannel : audioManager.getGuild().getVoiceChannels()) {
                audioManager.openAudioConnection(voiceChannel);
                break;
            }
        }
    }

    private static synchronized GuildMusicManager getGuildAudioPlayer(Guild guild) {
        long guildId = Long.parseLong(guild.getId());
        GuildMusicManager musicManager = MUSIC_MANAGER.get(guildId);

        if (musicManager == null) {
            musicManager = new GuildMusicManager(AUDIO_PLAYER_MANAGER);
            MUSIC_MANAGER.put(guildId, musicManager);
        }

        guild.getAudioManager().setSendingHandler(musicManager.getSendHandler());

        return musicManager;
    }

    private static int getQueueSize(GuildMusicManager manager) {
        return manager.getPlayer().getPlayingTrack() == null ?
                manager.scheduler.getQueue().size() :
                manager.scheduler.getQueue().size() + 1;
    }
}

@@ -3569,16 +3569,21 @@
         
+if (!
 connectT
@@ -3575,37 +3575,32 @@
   if (!connectTo
-First
 VoiceChannel(mes
@@ -3607,39 +3607,147 @@
 sage
-.getGuild().getAudioManager());
+)) %7B%0A            MessageFactory.makeWarning(message, %22You have to be connected to a voice channel.%22).queue();%0A            return;%0A        %7D
 %0A%0A  
@@ -3836,20 +3836,23 @@
  static 
-void
+boolean
  connect
@@ -3857,13 +3857,8 @@
 ctTo
-First
 Voic
@@ -3870,36 +3870,100 @@
 nel(
-AudioManager audioManager) %7B
+Message message) %7B%0A        AudioManager audioManager = message.getGuild().getAudioManager();
 %0A   
@@ -4055,21 +4055,16 @@
         
-for (
 VoiceCha
@@ -4072,44 +4072,35 @@
 nel 
-voiceC
+c
 hannel 
-: audioMan
+= mess
 age
-r
 .get
-Guild
+Member
 ().g
@@ -4110,83 +4110,204 @@
 oice
+State().get
 Channel
-s
 ()
-) %7B%0A                audioManager.openAudioConnection(voice
+;%0A%0A            if (channel == null) %7B%0A                return false;%0A            %7D%0A%0A            audioManager.openAudioConnection(message.getMember().getVoiceState().get
 Channel
+()
 );%0A 
@@ -4313,24 +4313,26 @@
         
+%7D%0A
         
 break;%0A 
@@ -4327,38 +4327,20 @@
     
-break;%0A            %7D%0A        %7D
+return true;
 %0A   

Change music to connect to the same voice channel as the author