package leigh.minecraft.link.cmd;

import leigh.mecha.cli.CommandFrame;
import leigh.mecha.log.MechaLogger;
import leigh.mecha.log.MechaLoggerFactory;
import leigh.mecha.mq.Fanout;
import leigh.minecraft.link.bukkit.BukkitCommandState;
import leigh.minecraft.link.faction.Reputation;
import leigh.minecraft.link.item.XPBottle;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

/**
 * This class is the incoming, event-based link between Bukkit and the plugin. We register all of our handlers here,
 * to reduce load on the server, which has to process each class registered for each event.
 *
 * @author Alex Leigh
 */
public class LCCommandHandler implements CommandExecutor {
    private static final MechaLogger logger = MechaLoggerFactory.getLogger(LCCommandHandler.class);
    private final Fanout<PlayerCommand> playerCommandFanout = new Fanout<>();
    private final Reputation reputation;
    private final CommandFrame<BukkitCommandState> xpCommandFrame;

    public LCCommandHandler(Reputation reputation, XPBottle xpBottle) {
        this.reputation = reputation;
        xpCommandFrame = xpBottle.getCommandFrame();
    }

    public Fanout<PlayerCommand> getPlayerCommandFanout() {
        return playerCommandFanout;
    }

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        logger.info("onCommand called. [sender: {}] [command: {}] [args: {}]", sender, command, args);

        // Note that bukkit strips the command LC

        if (args.length == 0) {
            sender.sendMessage("Usage: /lc stuff");
            return true;
        }

        // Hack in /lc xp. At this point args is something like "xp craft 10"
        if ("xp".equals(args[0])) {
            logger.info("XP command injection hack");
            try {
                xpCommandFrame.handle(args, new BukkitCommandState(sender.getServer().getPlayer(sender.getName())));
            } catch (Exception e) {
                e.printStackTrace();
            }
            return true;
        }

        // Hack in /lc rep
        if ("rep".equals(args[0])) {
            Player p = Bukkit.getPlayer(sender.getName());
            if (p != null) {
                int factionId = Integer.parseInt(args[1]);
                int delta = Integer.parseInt(args[2]);
                reputation.adjustReputation(p.getUniqueId(), factionId, delta);
            }
            return true;
        }

        PlayerCommand pc = new PlayerCommand(sender, command, args);
        // TODO: Executor pool!
        new Thread(() -> playerCommandFanout.write(pc)).start();
        return true;
    }
}
