<commit_before>package com.github.alex1304.ultimategdbot.modules.commands;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.github.alex1304.ultimategdbot.core.UltimateGDBot;
import com.github.alex1304.ultimategdbot.exceptions.CommandFailedException;
import com.github.alex1304.ultimategdbot.exceptions.InvalidCommandArgsException;
import com.github.alex1304.ultimategdbot.exceptions.ModuleUnavailableException;
import com.github.alex1304.ultimategdbot.modules.reply.Reply;
import com.github.alex1304.ultimategdbot.modules.reply.ReplyModule;
import com.github.alex1304.ultimategdbot.utils.BotUtils;

import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent;
import sx.blah.discord.handle.obj.IMessage;
import sx.blah.discord.util.EmbedBuilder;

/**
 * An interactive menu is a command which only role is to provide nested commands,
 * accessible via an interactive menu or directly via args.
 * 
 * @author Alex1304
 *
 */
public abstract class InteractiveMenu implements Command {

	private Map<String, Command> subCommandMap;
	private String menuEmbedContent;
	private String menuContent;

	public InteractiveMenu() {
		this.subCommandMap = new ConcurrentHashMap<>();
		this.menuEmbedContent = "";
		this.menuContent = "";
	}

	/**
	 * Triggers a subcommand by giving its name
	 * 
	 * @param cmdName
	 *            - The name of the sub-command to trigger
	 * @param event
	 *            - the Discord event info provided by the parent core command
	 * @param args
	 *            - arguments to give to the subcommand
	 * @return false if the command could not be found or failed to execute, true otherwise
	 */
	public boolean triggerSubCommand(String cmdName, MessageReceivedEvent event, List<String> args) {
		if (subCommandMap.containsKey(cmdName)) {
			CommandsModule.executeCommand(subCommandMap.get(cmdName), event, args);
			return true;
		} else
			return false;
	}
	
	@Override
	public final void runCommand(MessageReceivedEvent event, List<String> args) throws CommandFailedException {
		InvalidCommandArgsException invalidArgsException = new InvalidCommandArgsException(
				this.buildInvalidSyntaxMessage(event.getMessage().getContent()));
		
		if (!args.isEmpty()) { // First tries to guess subcommand in args
			if (!subCommandMap.containsKey(args.get(0)))
				throw invalidArgsException;
			
			triggerSubCommand(args.get(0), event, args.subList(1, args.size()));
			return;
		}

		// If no subcommand could be resolved with args, we will ask the user
		// using an interactive menu
		try {
			ReplyModule rm = (ReplyModule) UltimateGDBot.getModule("reply");
			<commit_msg>Subcommands are now case insensitive<commit_after>package com.github.alex1304.ultimategdbot.modules.commands;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.github.alex1304.ultimategdbot.core.UltimateGDBot;
import com.github.alex1304.ultimategdbot.exceptions.CommandFailedException;
import com.github.alex1304.ultimategdbot.exceptions.InvalidCommandArgsException;
import com.github.alex1304.ultimategdbot.exceptions.ModuleUnavailableException;
import com.github.alex1304.ultimategdbot.modules.reply.Reply;
import com.github.alex1304.ultimategdbot.modules.reply.ReplyModule;
import com.github.alex1304.ultimategdbot.utils.BotUtils;

import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent;
import sx.blah.discord.handle.obj.IMessage;
import sx.blah.discord.util.EmbedBuilder;

/**
 * An interactive menu is a command which only role is to provide nested commands,
 * accessible via an interactive menu or directly via args.
 * 
 * @author Alex1304
 *
 */
public abstract class InteractiveMenu implements Command {

	private Map<String, Command> subCommandMap;
	private String menuEmbedContent;
	private String menuContent;

	public InteractiveMenu() {
		this.subCommandMap = new ConcurrentHashMap<>();
		this.menuEmbedContent = "";
		this.menuContent = "";
	}

	/**
	 * Triggers a subcommand by giving its name
	 * 
	 * @param cmdName
	 *            - The name of the sub-command to trigger
	 * @param event
	 *            - the Discord event info provided by the parent core command
	 * @param args
	 *            - arguments to give to the subcommand
	 * @return false if the command could not be found or failed to execute, true otherwise
	 */
	public boolean triggerSubCommand(String cmdName, MessageReceivedEvent event, List<String> args) {
		if (subCommandMap.containsKey(cmdName.toLowerCase())) {
			CommandsModule.executeCommand(subCommandMap.get(cmdName.toLowerCase()), event, args);
			return true;
		} else
			return false;
	}
	
	@Override
	public final void runCommand(MessageReceivedEvent event, List<String> args) throws CommandFailedException {
		InvalidCommandArgsException invalidArgsException = new InvalidCommandArgsException(
				this.buildInvalidSyntaxMessage(event.getMessage().getContent()));
		
		if (!args.isEmpty()) { // First tries to guess subcommand in args
			if (!subCommandMap.containsKey(args.get(0).toLowerCase()))
				throw invalidArgsException;
			
			triggerSubCommand(args.get(0), event, args.subList(1, args.size()));
			return;
		}

		// If no subcommand could be resolved with args, we will ask the user
		// using an interactive menu
		try {
			ReplyModule rm = (ReplyModule) UltimateGDBot.getModule("reply");
			
{'fraction_non_alphanumeric': 0.09237241631607829, 'fraction_numerical': 0.014267422718126943, 'mean_word_length': 4.579591836734694, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '986825', 'n_tokens_mistral': 1725, 'n_tokens_neox': 1560, 'n_words': 408}