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.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket;
import net.minecraft.network.packet.s2c.play.GameStateChangeS2CPacket;
import net.minecraft.text.Text;

import java.util.Timer;
import java.util.TimerTask;

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

public class SelfCare implements Listener {
    public static final SelfCare INSTANCE = new SelfCare(MinecraftClient.getInstance(), 500L); // make the intervals in config?
    public final long interval;
    private final MinecraftClient client;
    public boolean opEnabled = ChipmunkMod.CONFIG.selfCare.op;
    public boolean gamemodeEnabled = ChipmunkMod.CONFIG.selfCare.gameMode;
    public boolean cspyEnabled = ChipmunkMod.CONFIG.selfCare.cspy;
    public String skin;
    public boolean hasSkin = false;
    private int gameMode;
    private Timer timer;
    private boolean cspy = false;

    public SelfCare (final MinecraftClient client, final long interval) {
        this.client = client;
        this.interval = interval;

        this.skin = ChipmunkMod.CONFIG.autoSkinUsername == null ? "off" : ChipmunkMod.CONFIG.autoSkinUsername;

        ListenerManager.addListener(this);
    }

    public void init () {
    }

    public void onJoin () {
        final TimerTask task = new TimerTask() {
            public void run () {
                tick();
            }
        };

        timer = new Timer();

        timer.schedule(task, interval, interval);
    }

    public void cleanup () {
        if (timer == null) return;

        timer.cancel();
        timer.purge();

        gameMode = -1;

        hasSkin = false;
        cspy = false;
    }

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

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

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

    public void tick () {
        final ClientPlayerEntity player = client.player;
        final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();

        if (networkHandler == null) {
            cleanup();
            return;
        }

        if (player != null && !player.hasPermissionLevel(2) && opEnabled && serverHasCommand("op"))
            networkHandler.sendChatCommand("op @s[type=player]");
        else if (gameMode != 1 && gamemodeEnabled)
            networkHandler.sendChatCommand("gamemode creative");
        else if (!cspy && cspyEnabled && serverHasCommand("c"))
            networkHandler.sendChatCommand("c on");
        else if (!hasSkin && !skin.equalsIgnoreCase("off"))
            networkHandler.sendChatCommand("skin " + skin);
    }

    @Override
    public void packetReceived (final Packet<?> packet) {
        if (packet instanceof GameJoinS2CPacket) packetReceived((GameJoinS2CPacket) packet);
        else if (packet instanceof GameStateChangeS2CPacket) packetReceived((GameStateChangeS2CPacket) packet);
    }

    public void packetReceived (final GameJoinS2CPacket packet) {
        gameMode = packet.commonPlayerSpawnInfo().gameMode().getId();
    }

    public void packetReceived (final GameStateChangeS2CPacket packet) {
        if (packet.getReason() != GameStateChangeS2CPacket.GAME_MODE_CHANGED) return;

        gameMode = (int) packet.getValue();
    }
}
