package me.despawningbone.discordbot.command.info;

import java.awt.Color;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;
import java.util.List;
import java.util.Map.Entry;

import org.apache.commons.lang3.exception.ExceptionUtils;

import me.despawningbone.discordbot.DiscordBot;
import me.despawningbone.discordbot.command.Command;
import me.despawningbone.discordbot.command.CommandResult;
import me.despawningbone.discordbot.command.CommandResult.CommandResultType;
import me.despawningbone.discordbot.utils.MiscUtils;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.User;

public class Help extends Command {
	public Help() {
		this.desc = "Shows command usage and relevant details.";
		this.usage = "[commandname]";
		this.remarks = Arrays.asList("Specify a command name to see details about it!");
	}

	//private MessageEmbed embed = null;

	//TODO invoke this on INVALIDARGS
	@Override
	public CommandResult execute(TextChannel channel, User author, Message msg, String[] args) {  //add command rank required? add category?
		try(Connection con = DiscordBot.db.getConnection(); Statement s = con.createStatement()) {
			String prefix = MiscUtils.getPrefix(s, channel.getGuild().getId());
			if (args.length < 1) {
				EmbedBuilder em = new EmbedBuilder();
				em.setAuthor("despbot's Commands", null,
						channel.getJDA().getSelfUser().getAvatarUrl());
				for (Entry<String, List<Command>> entry : DiscordBot.catCmds.entrySet()) {
					String content = "";
					List<Command> cmds = entry.getValue();
					for (Command cmd : cmds) {
						String cmdInfo = prefix + cmd.getName() + " " + cmd.getUsage() + " - " + cmd.getDesc() + "\n";
						//if(cmd.isDisabled(channel.getGuild().getId())) content += "*" + cmdInfo.substring(0, cmdInfo.length() - 2)  + "*\n";  //TODO migrate to SQLite  //seems to have too much overhead
						/*else*/ content += cmdInfo;
					}
					em.addField(entry.getKey(), content, false);
					em.addBlankField(false);
				}
				em.getFields().remove(em.getFields().size() - 1);
				em.setFooter("Do " + prefix + "help [cmdname] for more information about the command!",
						null);
				em.setColor(new Color(10,182,246));
				channel.sendMessageEmbeds(em.build()).queue();
				return new CommandResult(CommandResultType.SUCCESS);
			} else {
				Command cmd = DiscordBot.commands.get(args[0]);
				if (cmd == null) {
					cmd = DiscordBot.aliases.get(args[0]);
					if (cmd == null) {
						return new CommandResult(CommandResultType.INVALIDARGS, "Invalid command!");
					}
				}
				String missing;
				String name = cmd.getName(); String desc = "";
				EmbedBuilder em = new EmbedBuilder();  //DONE show permission required

				for(int i = 1; i < args.length; i++) {
					cmd = cmd.getSubCommand(args[i]);
					if(cmd == null) return new CommandResult(CommandResultType.INVALIDARGS, "Invalid sub command! Check `" + prefix + "help " + String.join(" ", Arrays.copyOfRange(args, 0, i)) + "` for more info.");
					name += " " + cmd.getName();
				}
				
				/*em.setDescription(cmd.getDesc());
				em.addField("Usage", DiscordBot.prefix + " " + cmd.getName() + " " + cmd.getUsage() + (cmd.getRemarks() == null ? "" : "\n\n" + String.join("\n", cmd.getRemarks())), false);
				if(cmd.getAliases() != null) em.addField("Alias(es)",  String.join(", ", cmd.getAliases()), false);*/
				desc = (cmd.getAliases() != null ? "*Alias(es): " + String.join(", ", cmd.getAliases()) + "*\n\n**" : "**")
						+ cmd.getDesc() + "**\n" + "Usage: `" + prefix + name + (cmd.getUsage() == null || cmd.getUsage().isEmpty() ? "" : " " + cmd.getUsage())
						+ (cmd.getRemarks() == null ? "`" : "`\n\n" + String.join("\n", cmd.getRemarks()).replaceAll(DiscordBot.prefix, prefix));  //TODO temporary fix for !desp roll 
				if(cmd.hasSubCommand()) {  //TODO italic?
					desc += "\n\nDo `" + prefix + "help " + cmd.getName() + " <subcommand>` for more information!\n\nAvailable sub commands:\n\n";
					for(String subCmd : cmd.getSubCommandNames()) {
						desc += prefix + cmd.getName() + " " + subCmd + " - " + cmd.getSubCommand(subCmd).getDesc().split("\n")[0] + "\n";
					}
				}
				String eg = "";
				if(cmd.getExamples() != null) {
					for(String example : cmd.getExamples()) eg += prefix + name + " " + example + "\n";
					em.addField("Examples", eg, true);
				}
				missing = MiscUtils.getRequiredPerms(MiscUtils.getActivePerms(s, channel, cmd), cmd.getRequiredBotUserLevel());
				
				boolean disabled = (missing != null && missing.equals("DISABLED")) || cmd.isDisabled(); 
				if(missing != null && !disabled) em.addField("Required permissions", missing.replaceAll("OR ", "OR \n"), true);  //DONE make it print regardless of member?
				em.setDescription(desc);
				em.setTitle("Information for " + prefix + name + (disabled ? " (disabled)" : "") + ":");
				em.setFooter("<> - required parameters, [] - optional parameters", null);
				em.setColor(new Color(4, 246, 254));
				channel.sendMessageEmbeds(em.build()).queue();
				return new CommandResult(CommandResultType.SUCCESS);
			}
		} catch (SQLException e) {
			return new CommandResult(CommandResultType.ERROR, ExceptionUtils.getStackTrace(e));
		}
	}
}
