package com.blamejared.mcbot.listeners;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.blamejared.mcbot.MCBot;
import com.blamejared.mcbot.commands.api.CommandRegistrar;
import com.blamejared.mcbot.util.GuildStorage;

import sx.blah.discord.api.events.EventSubscriber;
import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent;
import sx.blah.discord.handle.impl.events.guild.channel.message.MessageUpdateEvent;
import sx.blah.discord.handle.obj.IGuild;
import sx.blah.discord.handle.obj.IMessage;
import sx.blah.discord.util.RequestBuffer;

public enum CommandListener {

    INSTANCE;
    
    public static final String DEFAULT_PREFIX = "!";
	public static final String CMD_PATTERN = "(\\?)?(\\w+)(?:[^\\S](.*))?$";

    public static GuildStorage<String> prefixes = new GuildStorage<>(id -> DEFAULT_PREFIX);
    private static final Map<String, Pattern> patternCache = new HashMap<>();

    @EventSubscriber
    public void onMessageRecieved(MessageReceivedEvent event) {
        tryInvoke(event.getMessage());
    }
    
    @EventSubscriber
    public void onMessageEdited(MessageUpdateEvent event) {
        if (event.getMessage() != null) {
            tryInvoke(event.getMessage());
        }
    }
    
    private void tryInvoke(IMessage msg) {
        if (msg.getAuthor() == null || msg.getAuthor().isBot()) {
            return;
        }
        // Hardcoded check for "@K9 help" for a global help command
        if (msg.getMentions().contains(MCBot.instance.getOurUser())) {
            String content = msg.getContent().replaceAll("<@!?" + MCBot.instance.getOurUser().getLongID() + ">", "").trim();
            if (content.toLowerCase(Locale.ROOT).matches("^help.*")) {
                CommandRegistrar.INSTANCE.invokeCommand(msg, "help", content.substring(4).trim());
                return;
            }
        }
        Pattern pattern = patternCache.computeIfAbsent(getPrefix(msg.getGuild()), prefix -> Pattern.compile(Pattern.quote(prefix) + CMD_PATTERN, Pattern.DOTALL));
        Matcher matcher = pattern.matcher(msg.getContent());
        if (matcher.matches()) {
            if (CommandRegistrar.INSTANCE.getCommands().isEmpty()) {
                RequestBuffer.request(() -> msg.getChannel().sendMessage("The bot is still booting up, wait a few seconds and try again."));
            } else {
                boolean expand = matcher.group(1) != null;
                CommandRegistrar.INSTANCE.invokeCommand(msg, expand ? "trick" : matcher.group(2), expand ? matcher.group(2) + " " + matcher.group(3) : matcher.group(3));
            }
        }
    }

    public static String getPrefix(IGuild guild) {
        return guild == null ? DEFAULT_PREFIX : prefixes.get(guild);
    }
}

@@ -1145,24 +1145,26 @@
 %0A    %7D%0A    %0A
+//
     @EventSu
@@ -1164,32 +1164,34 @@
 EventSubscriber%0A
+//
     public void 
@@ -1226,32 +1226,34 @@
 eEvent event) %7B%0A
+//
         if (even
@@ -1274,24 +1274,26 @@
  != null) %7B%0A
+//
             
@@ -1319,24 +1319,26 @@
 Message());%0A
+//
         %7D%0A  
@@ -1331,24 +1331,26 @@
 //        %7D%0A
+//
     %7D%0A    %0A 

Remove support for calling commands on edit