package com.tiedup.remake.network.minigame;

import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.network.base.AbstractClientPacket;
import java.util.UUID;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;

/**
 *
 * Contains:
 * - Session UUID
 * - Result type (SUCCESS, MISSED, OUT_OF_PICKS)
 * - Remaining uses
 */
public class PacketLockpickMiniGameResult extends AbstractClientPacket {

    public enum ResultType {
        /**
         * Successfully picked the lock
         */
        SUCCESS(0),

        /**
         * Missed the sweet spot
         */
        MISSED(1),

        /**
         * Ran out of lockpick uses
         */
        OUT_OF_PICKS(2),

        /**
         * Session cancelled
         */
        CANCELLED(3);

        private final int id;

        ResultType(int id) {
            this.id = id;
        }

        public int getId() {
            return id;
        }

        public static ResultType fromId(int id) {
            return switch (id) {
                case 0 -> SUCCESS;
                case 1 -> MISSED;
                case 2 -> OUT_OF_PICKS;
                case 3 -> CANCELLED;
                default -> MISSED;
            };
        }
    }

    private final UUID sessionId;
    private final ResultType resultType;
    private final int remainingUses;
    private final float distance; // Distance to sweet spot (0.0-1.0), used for MISSED animation

    public PacketLockpickMiniGameResult(
        UUID sessionId,
        ResultType resultType,
        int remainingUses
    ) {
        this(sessionId, resultType, remainingUses, 0f);
    }

    public PacketLockpickMiniGameResult(
        UUID sessionId,
        ResultType resultType,
        int remainingUses,
        float distance
    ) {
        this.sessionId = sessionId;
        this.resultType = resultType;
        this.remainingUses = remainingUses;
        this.distance = distance;
    }

    public void encode(FriendlyByteBuf buf) {
        buf.writeUUID(sessionId);
        buf.writeVarInt(resultType.getId());
        buf.writeVarInt(remainingUses);
        buf.writeFloat(distance);
    }

    public static PacketLockpickMiniGameResult decode(FriendlyByteBuf buf) {
        UUID sessionId = buf.readUUID();
        ResultType resultType = ResultType.fromId(buf.readVarInt());
        int remainingUses = buf.readVarInt();
        float distance = buf.readFloat();
        return new PacketLockpickMiniGameResult(
            sessionId,
            resultType,
            remainingUses,
            distance
        );
    }

    @Override
    @OnlyIn(Dist.CLIENT)
    protected void handleClientImpl() {
        ClientHandler.handle(this);
    }

    @OnlyIn(Dist.CLIENT)
    private static class ClientHandler {

        private static void handle(PacketLockpickMiniGameResult pkt) {
            net.minecraft.client.Minecraft mc =
                net.minecraft.client.Minecraft.getInstance();
            if (mc.player == null) {
                return;
            }

            TiedUpMod.LOGGER.debug(
                "[PacketLockpickMiniGameResult] Received result: type={}, uses={}",
                pkt.resultType,
                pkt.remainingUses
            );

            if (
                mc.screen instanceof
                    com.tiedup.remake.client.gui.screens.LockpickMiniGameScreen screen
            ) {
                switch (pkt.resultType) {
                    case SUCCESS -> screen.onSuccess();
                    case MISSED -> screen.onMissed(
                        pkt.remainingUses,
                        pkt.distance
                    );
                    case OUT_OF_PICKS -> screen.onOutOfPicks();
                    case CANCELLED -> screen.onCancelled();
                }
            }
        }
    }

    // Getters
    public UUID getSessionId() {
        return sessionId;
    }

    public ResultType getResultType() {
        return resultType;
    }

    public int getRemainingUses() {
        return remainingUses;
    }

    public float getDistance() {
        return distance;
    }
}
