/*
 * Skybot, a multipurpose discord bot
 *      Copyright (C) 2017 - 2018  Duncan "duncte123" Sterken & Ramid "ramidzkh" Khan & Maurice R S "Sanduhr32"
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package ml.duncte123.skybot.commands.guild.mod;

import me.duncte123.botCommons.messaging.MessageUtils;
import ml.duncte123.skybot.objects.command.Command;
import ml.duncte123.skybot.objects.command.CommandCategory;
import ml.duncte123.skybot.objects.command.CommandContext;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.entities.Message;
import net.dv8tion.jda.core.entities.TextChannel;
import net.dv8tion.jda.core.events.message.guild.GuildMessageReceivedEvent;
import org.jetbrains.annotations.NotNull;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class CleanupCommand extends Command {

    public final static String help = "performs a cleanup in the channel where the command is run.";

    public CleanupCommand() {
        this.category = CommandCategory.MOD_ADMIN;
    }

    @Override
    public void executeCommand(@NotNull CommandContext ctx) {

        GuildMessageReceivedEvent event = ctx.getEvent();
        List<String> args = ctx.getArgs();

        if (!event.getMember().hasPermission(Permission.MESSAGE_MANAGE, Permission.MESSAGE_HISTORY)) {
            MessageUtils.sendMsg(event, "You don't have permission to run this command!");
            return;
        }

        int total = 5;
        boolean keepPinned = false;
        boolean clearBots = false;

        if (args.size() > 3) {
            MessageUtils.sendErrorWithMessage(event.getMessage(), "You provided more than three arguments.");
            return;
        }

        // if size == 0 then this will just be skipped
        for (String arg : args) {
            if (arg.equalsIgnoreCase("keep-pinned")) {
                keepPinned = true;
            } else if (arg.equalsIgnoreCase("bots-only")) {
                clearBots = true;
            } else if (isInteger(arg)) {
                try {
                    total = Integer.parseInt(args.get(0));
                } catch (NumberFormatException e) {
                    MessageUtils.sendError(event.getMessage());
                    MessageUtils.sendMsg(event, "Error: Amount to clear is not a valid number");
                    return;
                }
                if (total < 1 || total > 1000) {
                    MessageUtils.sendMsgAndDeleteAfter(event, 5, TimeUnit.SECONDS, "Error: count must be minimal 2 and maximal 1000");
                    return;
                }
            }
        }

        final boolean keepPinnedFinal = keepPinned;
        final boolean clearBotsFinal = clearBots;
        TextChannel channel = event.getChannel();
        channel.getIterableHistory().takeAsync(total).thenApplyAsync((msgs) -> {
            Stream<Message> msgStream = msgs.stream();

            if (keepPinnedFinal)
                msgStream = msgStream.filter(msg -> !msg.isPinned());
            if (clearBotsFinal)
                msgStream = msgStream.filter(msg -> msg.getAuthor().isBot());
            List<Message> msgList = msgStream.collect(Collectors.toList());
            channel.purgeMessages(msgList);
            return msgList.size();
        }).whenCompleteAsync((count, thr) -> {
            if (thr != null) {
                String cause = "";
                if (thr.getCause() != null)
                    cause = " caused by: " + thr.getCause().getMessage();
                MessageUtils.sendMsg(event, "ERROR: " + thr.getMessage() + cause);
                return;
            }
            MessageUtils.sendMsgFormatAndDeleteAfter(event, 10, TimeUnit.SECONDS,
                    "Removed %d messages!", count);
        }).exceptionally((thr) -> -1);
    }

    @Override
    public String help() {
        return "Performs a cleanup in the channel where the command is run.\n" +
                "Usage: `" + PREFIX + getName() + "[ammount] [keep-pinned]`";
    }

    @Override
    public String getName() {
        return "cleanup";
    }

    @Override
    public String[] getAliases() {
        return new String[]{"clear", "purge"};
    }
}

@@ -925,16 +925,56 @@
 eUtils;%0A
+import ml.duncte123.skybot.SinceSkybot;%0A
 import m
@@ -1572,110 +1572,8 @@
  %7B%0A%0A
-    public final static String help = %22performs a cleanup in the channel where the command is run.%22;%0A%0A
     
@@ -3228,32 +3228,82 @@
    %7D%0A        %7D%0A%0A
+        @SinceSkybot(version = %223.78.2_e89e53a5%22)%0A
         final bo
@@ -3434,24 +3434,59 @@
 tChannel();%0A
+        // Start of the annotation%0A
         chan
@@ -3819,24 +3819,25 @@
 ).isBot());%0A
+%0A
             
@@ -3896,24 +3896,25 @@
 .toList());%0A
+%0A
             
@@ -3995,79 +3995,33 @@
  %7D).
-whenCompleteAsync((count, thr) -%3E %7B%0A            if (thr != null) %7B%0A    
+exceptionally((thr) -%3E %7B%0A
     
@@ -4047,20 +4047,16 @@
 e = %22%22;%0A
-    
         
@@ -4103,20 +4103,16 @@
         
-    
 cause = 
@@ -4161,36 +4161,32 @@
 ();%0A            
-   
- 
 MessageUtils.sen
@@ -4244,34 +4244,32 @@
             
-    
 return
+ 0
 ;%0A          
@@ -4258,37 +4258,70 @@
 turn 0;%0A        
-    %7D
+%7D).whenCompleteAsync((count, thr) -%3E %7B
 %0A            Mes
@@ -4453,36 +4453,42 @@
   %7D)
-.exceptionally((thr) -%3E -1);
+;%0A        // End of the annotation
 %0A   
@@ -4687,16 +4687,28 @@
 -pinned%5D
+ %5Bbots-only%5D
 %60%22;%0A    
@@ -4880,16 +4880,24 @@
  %22purge%22
+, %22wipe%22
 %7D;%0A    %7D

Update CleanUpCommand's help & the CompletionStage's workflow