package net.minecraft.command;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import net.minecraft.entity.Entity;
import net.minecraft.util.BlockPos;
import net.minecraft.util.ChatComponentTranslation;
import net.minecraft.util.EnumChatFormatting;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class CommandHandler implements ICommandManager
{
    private static final Logger logger = LogManager.getLogger();
    /** Map of Strings to the ICommand objects they represent */
    private final Map commandMap = Maps.newHashMap();
    /** The set of ICommand objects currently loaded. */
    private final Set commandSet = Sets.newHashSet();
    private static final String __OBFID = "CL_00001765";

    public int executeCommand(ICommandSender sender, String command)
    {
        command = command.trim();

        if (command.startsWith("/"))
        {
            command = command.substring(1);
        }

        String[] astring = command.split(" ");
        String s1 = astring[0];
        astring = dropFirstString(astring);
        ICommand icommand = (ICommand)this.commandMap.get(s1);
        int i = this.getUsernameIndex(icommand, astring);
        int j = 0;
        ChatComponentTranslation chatcomponenttranslation;

        if (icommand == null)
        {
            chatcomponenttranslation = new ChatComponentTranslation("commands.generic.notFound", new Object[0]);
            chatcomponenttranslation.getChatStyle().setColor(EnumChatFormatting.RED);
            sender.addChatMessage(chatcomponenttranslation);
        }
        else if (icommand.canCommandSenderUseCommand(sender))
        {
            net.minecraftforge.event.CommandEvent event = new net.minecraftforge.event.CommandEvent(icommand, sender, astring);
            if (net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(event))
            {
                if (event.exception != null)
                {
                    com.google.common.base.Throwables.propagateIfPossible(event.exception);
                }
                return 1;
            }

            if (i > -1)
            {
                List list = PlayerSelector.func_179656_b(sender, astring[i], Entity.class);
                String s2 = astring[i];
                sender.func_174794_a(CommandResultStats.Type.AFFECTED_ENTITIES, list.size());
                Iterator iterator = list.iterator();

                while (iterator.hasNext())
                {
                    Entity entity = (Entity)iterator.next();
                    astring[i] = entity.getUniqueID().toString();

                    if (this.func_175786_a(sender, astring, icommand, command))
                    {
                        ++j;
                    }
                }

                astring[i] = s2;
            }
            else
            {
                sender.func_174794_a(CommandResultStats.Type.AFFECTED_ENTITIES, 1);

                if (this.func_175786_a(sender, astring, icommand, command))
                {
                    ++j;
                }
            }
        }
        else
        {
            chatcomponenttranslation = new ChatComponentTranslation("commands.generic.permission", new Object[0]);
            chatcomponenttranslation.getChatStyle().setColor(EnumChatFormatting.RED);
            sender.addChatMessage(chatcomponenttranslation);
        }

        sender.func_174794_a(CommandResultStats.Type.SUCCESS_COUNT, j);
        return j;
    }

    protected boolean func_175786_a(ICommandSender p_175786_1_, String[] p_175786_2_, ICommand p_175786_3_, String p_175786_4_)
    {
        ChatComponentTranslation chatcomponenttranslation;

        try
        {
            p_175786_3_.processCommand(p_175786_1_, p_175786_2_);
            return true;
        }
        catch (WrongUsageException wrongusageexception)
        {
            chatcomponenttranslation = new ChatComponentTranslation("commands.generic.usage", new Object[] {new ChatComponentTranslation(wrongusageexception.getMessage(), wrongusageexception.getErrorOjbects())});
            chatcomponenttranslation.getChatStyle().setColor(EnumChatFormatting.RED);
            p_175786_1_.addChatMessage(chatcomponenttranslation);
        }
        catch (CommandException commandexception)
        {
            chatcomponenttranslation = new ChatComponentTranslation(commandexception.getMessage(), commandexception.getErrorOjbects());
            chatcomponenttranslation.getChatStyle().setColor(EnumChatFormatting.RED);
            p_175786_1_.addChatMessage(chatcomponenttranslation);
        }
        catch (Throwable throwable)
        {
            chatcomponenttranslation = new ChatComponentTranslation("commands.generic.exception", new Object[0]);
            chatcomponenttranslation.getChatStyle().setColor(EnumChatFormatting.RED);
            p_175786_1_.addChatMessage(chatcomponenttranslation);
            logger.error("Couldn\'t process command: \'" + p_175786_4_ + "\'", throwable);
        }

        return false;
    }

    /**
     * adds the command and any aliases it has to the internal map of available commands
     */
    public ICommand registerCommand(ICommand p_71560_1_)
    {
        this.commandMap.put(p_71560_1_.getCommandName(), p_71560_1_);
        this.commandSet.add(p_71560_1_);
        Iterator iterator = p_71560_1_.getCommandAliases().iterator();

        while (iterator.hasNext())
        {
            String s = (String)iterator.next();
            ICommand icommand1 = (ICommand)this.commandMap.get(s);

            if (icommand1 == null || !icommand1.getCommandName().equals(s))
            {
                this.commandMap.put(s, p_71560_1_);
            }
        }

        return p_71560_1_;
    }

    /**
     * creates a new array and sets elements 0..n-2 to be 0..n-1 of the input (n elements)
     */
    private static String[] dropFirstString(String[] p_71559_0_)
    {
        String[] astring1 = new String[p_71559_0_.length - 1];
        System.arraycopy(p_71559_0_, 1, astring1, 0, p_71559_0_.length - 1);
        return astring1;
    }

    public List getTabCompletionOptions(ICommandSender sender, String input, BlockPos pos)
    {
        String[] astring = input.split(" ", -1);
        String s1 = astring[0];

        if (astring.length == 1)
        {
            ArrayList arraylist = Lists.newArrayList();
            Iterator iterator = this.commandMap.entrySet().iterator();

            while (iterator.hasNext())
            {
                Entry entry = (Entry)iterator.next();

                if (CommandBase.doesStringStartWith(s1, (String)entry.getKey()) && ((ICommand)entry.getValue()).canCommandSenderUseCommand(sender))
                {
                    arraylist.add(entry.getKey());
                }
            }

            return arraylist;
        }
        else
        {
            if (astring.length > 1)
            {
                ICommand icommand = (ICommand)this.commandMap.get(s1);

                if (icommand != null && icommand.canCommandSenderUseCommand(sender))
                {
                    return icommand.addTabCompletionOptions(sender, dropFirstString(astring), pos);
                }
            }

            return null;
        }
    }

    /**
     * returns all commands that the commandSender can use
     */
    public List getPossibleCommands(ICommandSender sender)
    {
        ArrayList arraylist = Lists.newArrayList();
        Iterator iterator = this.commandSet.iterator();

        while (iterator.hasNext())
        {
            ICommand icommand = (ICommand)iterator.next();

            if (icommand.canCommandSenderUseCommand(sender))
            {
                arraylist.add(icommand);
            }
        }

        return arraylist;
    }

    /**
     * returns a map of string to commads. All commands are returned, not just ones which someone has permission to use.
     */
    public Map getCommands()
    {
        return this.commandMap;
    }

    /**
     * Return a command's first parameter index containing a valid username.
     */
    private int getUsernameIndex(ICommand p_82370_1_, String[] p_82370_2_)
    {
        if (p_82370_1_ == null)
        {
            return -1;
        }
        else
        {
            for (int i = 0; i < p_82370_2_.length; ++i)
            {
                if (p_82370_1_.isUsernameIndex(p_82370_2_, i) && PlayerSelector.matchesMultiplePlayers(p_82370_2_[i]))
                {
                    return i;
                }
            }

            return -1;
        }
    }
}