package com.avairebot.orion.handlers;

import com.avairebot.orion.Orion;
import com.avairebot.orion.Statistics;
import com.avairebot.orion.commands.CommandContainer;
import com.avairebot.orion.commands.CommandHandler;
import com.avairebot.orion.contracts.handlers.EventHandler;
import com.avairebot.orion.database.controllers.GuildController;
import com.avairebot.orion.database.controllers.PlayerController;
import com.avairebot.orion.database.transformers.GuildTransformer;
import com.avairebot.orion.database.transformers.PlayerTransformer;
import com.avairebot.orion.factories.MessageFactory;
import com.avairebot.orion.level.LevelManager;
import com.avairebot.orion.middleware.MiddlewareStack;
import net.dv8tion.jda.core.events.message.MessageReceivedEvent;

import java.util.concurrent.CompletableFuture;
import java.util.regex.Pattern;

public class MessageCreateEvent extends EventHandler {

    public MessageCreateEvent(Orion orion) {
        super(orion);
    }

    @Override
    public void onMessageReceived(MessageReceivedEvent event) {
        Statistics.addMessage();

        if (event.getAuthor().isBot()) {
            return;
        }

        loadDatabasePropertiesIntoMemory(event).thenAccept(properties -> {
            if (properties.getGuild() != null && properties.getPlayer() != null) {
                LevelManager.rewardPlayer(orion, event, properties.getGuild(), properties.getPlayer());
            }

            CommandContainer container = CommandHandler.getCommand(event.getMessage());
            if (container != null && canExecuteCommand(event, container)) {
                Statistics.addCommands();

                (new MiddlewareStack(orion, event.getMessage(), container)).next();
            }

            if (isMentionableCommand(event)) {
                container = CommandHandler.getCommandWithPriority(event.getMessage().getContent().split(" ")[1]);
                if (container != null && canExecuteCommand(event, container)) {
                    Statistics.addCommands();

                    (new MiddlewareStack(orion, event.getMessage(), container, true)).next();
                }
            }
        });
    }

    private boolean canExecuteCommand(MessageReceivedEvent event, CommandContainer container) {
        if (!container.getCommand().isAllowedInDM() && !event.getChannelType().isGuild()) {
            MessageFactory.makeWarning(event.getMessage(), ":warning: You can not use this command in direct messages!").queue();
            return false;
        }
        return true;
    }

    private boolean isMentionableCommand(MessageReceivedEvent event) {
        if (!event.getMessage().isMentioned(orion.getJDA().getSelfUser())) {
            return false;
        }

        String[] args = event.getMessage().getRawContent().split(" ");
        return args.length >= 2 && Pattern.compile("<@(!|)+" + orion.getJDA().getSelfUser().getId() + "+>", Pattern.CASE_INSENSITIVE)
                .matcher(args[0]).matches();

    }

    private CompletableFuture<DatabaseProperties> loadDatabasePropertiesIntoMemory(final MessageReceivedEvent event) {
        return CompletableFuture.supplyAsync(() -> {
            if (!event.getChannelType().isGuild()) {
                return new DatabaseProperties(null, null);
            }

            GuildTransformer guild = GuildController.fetchGuild(orion, event.getMessage());
            if (guild == null || !guild.isLevels()) {
                return new DatabaseProperties(guild, null);
            }
            return new DatabaseProperties(guild, PlayerController.fetchPlayer(orion, event.getMessage()));
        });
    }

    private class DatabaseProperties {

        private final GuildTransformer guild;
        private final PlayerTransformer player;

        DatabaseProperties(GuildTransformer guild, PlayerTransformer player) {
            this.guild = guild;
            this.player = player;
        }

        public GuildTransformer getGuild() {
            return guild;
        }

        public PlayerTransformer getPlayer() {
            return player;
        }
    }
}

@@ -890,24 +890,136 @@
 tHandler %7B%0A%0A
+    private static final Pattern userRegEX = Pattern.compile(%22%3C@(!%7C)+%5B0-9%5D%7B16,%7D+%3E%22, Pattern.CASE_INSENSITIVE);%0A%0A
     public M
@@ -2956,150 +2956,178 @@
 2 &&
- Pattern.compile(%22%3C@(!%7C)+%22 + orion.getJDA().getSelf
+%0A                userRegEX.matcher(args%5B0%5D).matches() &&%0A                event.getMessage().getMentioned
 User
+s
 ().get
-Id() + %22+%3E%22, Pattern.CASE_INSENSITIVE)%0A                .matcher(args%5B0%5D).matches(
+(0).getId().equals(orion.getJDA().getSelfUser().getId()
 );%0A%0A

Change message create mentionable commands pattern