package land.chipmunk.chipmunkmod.modules;

import land.chipmunk.chipmunkmod.ChipmunkMod;
import land.chipmunk.chipmunkmod.listeners.Listener;
import land.chipmunk.chipmunkmod.listeners.ListenerManager;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ServerboundChangeGameModePacket;
import net.minecraft.server.permissions.Permissions;
import net.minecraft.world.level.GameType;

import static land.chipmunk.chipmunkmod.util.ServerUtilities.serverHasCommand;

public class SelfCare implements Listener {
    public static final SelfCare INSTANCE = new SelfCare(Minecraft.getInstance());

    private final Minecraft client;

    public boolean configOpEnabled = ChipmunkMod.CONFIG.selfCare.op;
    public boolean configGameModeEnabled = ChipmunkMod.CONFIG.selfCare.gameMode;
    public boolean configCommandSpyEnabled = ChipmunkMod.CONFIG.selfCare.cspy;

    public GameType targetGameMode = GameType.CREATIVE;

    public String targetSkin;
    public boolean hasSkin = false;

    public String targetPrefix;
    public boolean hasPrefix = false;

    private boolean isCommandSpyEnabled = false;

    public SelfCare (final Minecraft client) {
        this.client = client;

        this.targetSkin = ChipmunkMod.CONFIG.autoSkinUsername == null ? "off" : ChipmunkMod.CONFIG.autoSkinUsername;
        this.targetPrefix = ChipmunkMod.CONFIG.autoPrefix == null ? "off" : ChipmunkMod.CONFIG.autoPrefix;

        ListenerManager.addListener(this);
    }

    public void init () {
    }

    public void cleanup () {
        hasSkin = false;
        hasPrefix = false;
        isCommandSpyEnabled = false;
    }

    @Override
    public void chatMessageReceived (final Component message) {
        final String stringMessage = message.getString();

        if (stringMessage.equals("Successfully enabled CommandSpy")) isCommandSpyEnabled = true;
        else if (stringMessage.equals("Successfully disabled CommandSpy")) isCommandSpyEnabled = false;

        else if (stringMessage.equals("Successfully set your skin to " + targetSkin + "'s")) hasSkin = true;
        else if (
                stringMessage.equals("Successfully removed your skin")
                        || stringMessage.startsWith("Successfully set your skin to ")
        ) hasSkin = false;

        else if (
                stringMessage.equals("You now have the tag: " + targetPrefix)
                        || stringMessage.equals("Something went wrong while saving the prefix. Please check console.")
        ) hasPrefix = true;
        else if (
                stringMessage.startsWith("You no longer have a tag")
                        || stringMessage.startsWith("You now have the tag: ")
        ) hasPrefix = false;
    }

    @Override
    public void timeUpdate () {
        final LocalPlayer player = client.player;
        final ClientPacketListener networkHandler = client.getConnection();

        if (networkHandler == null || player == null) return;

        if (
                !player.permissions().hasPermission(Permissions.COMMANDS_OWNER)
                        && configOpEnabled
                        && serverHasCommand("op")
        ) {
            networkHandler.sendCommand("op @s[type=player]");
        } else if (player.gameMode() != targetGameMode && configGameModeEnabled) {
            // ViaVersion will automatically convert this to `/gamemode creative`
            networkHandler.send(new ServerboundChangeGameModePacket(targetGameMode));
        } else if (!isCommandSpyEnabled && configCommandSpyEnabled && serverHasCommand("c")) {
            if (
                    CommandCore.INSTANCE.isSingleBlock
                            || !CommandCore.INSTANCE.ready
                            || !CommandCore.INSTANCE.runFillCommand
                            || !player.canUseGameMasterBlocks()
            ) {
                networkHandler.sendCommand("c on");
            } else {
                CommandCore.INSTANCE.run("c " + player.getStringUUID() + " on");
            }
        } else if (!hasSkin && serverHasCommand("skin") && !targetSkin.equalsIgnoreCase("off")) {
            networkHandler.sendCommand("skin " + targetSkin);
        } else if (!hasPrefix && serverHasCommand("prefix") && !targetPrefix.equalsIgnoreCase("off")) {
            networkHandler.sendCommand("prefix " + targetPrefix);
        }
    }

    @Override
    public void packetSent (final Packet<?> packet) {
        if (packet instanceof ServerboundChangeGameModePacket (final GameType mode)) {
            targetGameMode = mode;
        }
    }
}
