package fredboat.command.moderation;

import fredboat.FredBoat;
import fredboat.audio.player.AudioLossCounter;
import fredboat.audio.player.GuildPlayer;
import fredboat.audio.player.PlayerRegistry;
import fredboat.commandmeta.abs.Command;
import fredboat.commandmeta.abs.CommandContext;
import fredboat.commandmeta.abs.ICommandRestricted;
import fredboat.messaging.CentralMessaging;
import fredboat.messaging.internal.Context;
import fredboat.perms.PermissionLevel;
import fredboat.perms.PermsUtil;
import fredboat.shared.constant.BotConstants;
import fredboat.util.Emojis;
import net.dv8tion.jda.core.EmbedBuilder;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.entities.Guild;
import net.dv8tion.jda.core.entities.Member;
import net.dv8tion.jda.core.entities.TextChannel;
import net.dv8tion.jda.core.entities.VoiceChannel;

import javax.annotation.Nonnull;
import java.util.List;

public class DebugCommand extends Command implements ICommandRestricted {
    @Override
    public void onInvoke(CommandContext context) {

        if (context.args.length == 2 || context.args.length == 1) {

            Guild guild;
            if (context.args.length == 1) {
                guild = context.guild;
            } else {
                try {

                    if (!PermsUtil.checkPermsWithFeedback(PermissionLevel.BOT_ADMIN, context)) {
                        return;
                    }

                    guild = FredBoat.getGuildById(Long.valueOf(context.args[1]));
                } catch (Exception ignored){
                    guild = null;
                }

            }

            if (guild != null) {
                GuildPlayer player = PlayerRegistry.get(guild);

                sendEmbedResponse(context, player);
                return;
            }
            context.replyWithName("This guild does not exist!");
        }
    }

    private void sendEmbedResponse(CommandContext context, GuildPlayer player) {
        EmbedBuilder embed = CentralMessaging.getClearThreadLocalEmbedBuilder();
        embed.setTitle("Debug information for \"" + player.getGuild().getName() + "\"");

        StringBuilder str = new StringBuilder();
        str
                //.append(getAudioDebug(player)) doesn't work currently
                .append(getPlayerDebug(player))
                .append(getVoiceChannelDebug(player))
                .append(getAllTextChannelDebug(player.getGuild()))
                .append(getAllVoiceChannelDebug(player.getGuild()));
        embed.setDescription(str);
        embed.setColor(BotConstants.FREDBOAT_COLOR);

        try {
            context.reply(embed.build());
        } catch (Exception ex) {
            context.replyWithMention("Unable to send embed " + ex);
        }

    }

    private String getAudioDebug(GuildPlayer player) {
        int deficit = AudioLossCounter.EXPECTED_PACKET_COUNT_PER_MIN - (player.getAudioLossCounter().getLastMinuteLoss() + player.getAudioLossCounter().getLastMinuteSuccess());

        return "**Audio Debug**```\n"
                + "Packets sent:   " + player.getAudioLossCounter().getLastMinuteSuccess() + "\n"
                + "Null packets:   " + player.getAudioLossCounter().getLastMinuteLoss() + "\n"
                + "Packet deficit: " + deficit + "```\n";
    }

    private String getVoiceChannelDebug(GuildPlayer player) {

        VoiceChannel vc = player.getCurrentVoiceChannel();
        if (vc != null) {
            List<Member> vcUsers = player.getHumanUsersInCurrentVC();
            StringBuilder str = new StringBuilder();
            for (Member user : vcUsers) {
                str.append(user.getEffectiveName()).append(" ");
            }

            return "**VoiceChannel Debug**```\n"
                    + "Current vc: "  + vc.getName() + "\n"
                    + "Users in vc:\n" + str + "```\n";
        }

        return "**VoiceChannel Debug**```\n"
                + "Current vc: null```\n";
    }

    private String getPlayerDebug(GuildPlayer player) {
        String response = "**Player Debug**```\n"
                + "IsPlaying:  " + player.isPlaying() + "\n"
                + "Shuffle:    " + player.isShuffle() + "\n"
                + "Repeat:     " + player.getRepeatMode() + "\n";

        if (player.isPlaying()) {
            response = response + "Queue size: " + player.getTrackCount() + "\n";
        }
        return response + "```\n";
    }

    private String getAllTextChannelDebug(Guild guild) {
        StringBuilder str = new StringBuilder("**TextChannel Permissions**\n```");
        for (TextChannel channel : guild.getTextChannels()) {

            if (channel.canTalk()) {
                str.append(Emojis.OK).append(" - ");
            } else {
                str.append(Emojis.BAD).append(" - ");
            }
            str.append(channel.getName()).append("\n");
        }
        return str + "```\n";
    }

    private String getAllVoiceChannelDebug(Guild guild) {
        StringBuilder str = new StringBuilder("**VoiceChannel Permissions**\n```");
        for (VoiceChannel channel : guild.getVoiceChannels()) {

            if (channel.getGuild().getSelfMember().hasPermission(channel, Permission.VOICE_CONNECT)
                && channel.getGuild().getSelfMember().hasPermission(channel, Permission.VOICE_SPEAK)) {
                str.append(Emojis.OK).append(" - ");
            } else {
                str.append(Emojis.BAD).append(" - ");
            }
            str.append(channel.getName()).append("\n");
        }
        return str + "```\n";
    }

    @Nonnull
    @Override
    public String help(@Nonnull Context context) {
        return "{0}{1] <guildId>\n#Display debug information for the selected guild";
    }

    @Override
    public PermissionLevel getMinimumPerms() {
        return PermissionLevel.DJ;
    }
}

@@ -567,16 +567,62 @@
 Emojis;%0A
+import lavalink.client.player.LavalinkPlayer;%0A
 import n
@@ -651,24 +651,24 @@
 bedBuilder;%0A
-
 import net.d
@@ -1056,16 +1056,25 @@
 nInvoke(
+@Nonnull 
 CommandC
@@ -2315,16 +2315,66 @@
 rrently%0A
+                .append(getLavaLinkDebug(player))%0A
         
@@ -2859,32 +2859,408 @@
       %7D%0A%0A    %7D%0A%0A
+    private String getLavaLinkDebug(GuildPlayer player) %7B%0A        if (player.getPlayer() instanceof LavalinkPlayer) %7B%0A%0A            return  %22**LavaLink Debug**%60%60%60%5Cn%22%0A                    + %22State: %22 + ((LavalinkPlayer) player.getPlayer()).getLink().getState() + %22%60%60%60%5Cn%22;%0A        %7D%0A        return  %22**LavaLink Debug**%60%60%60%5Cn%22%0A                + %22Not a LavaLink player%60%60%60%5Cn%22;%0A    %7D%0A%0A
     private Stri

Debug command now has Debug (duh..) info about LavaLink (#342)