package me.earthme.luminol.collision;

import me.earthme.luminol.collision.backend.FFMCollisionBackend;
import me.earthme.luminol.collision.backend.GPUCollisionBackend;
import me.earthme.luminol.collision.backend.JavaCollisionBackend;
import me.earthme.luminol.config.modules.optimizations.AcceleratedCollisionConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class CollisionBackendSelector {

    private static final Logger LOGGER = LoggerFactory.getLogger("NekoCore/Collision");
    private static volatile INativeCollisionBackend activeBackend = null;
    private static volatile boolean vanilla = false;

    private CollisionBackendSelector() {}

    public static void initialize() {
        if (!AcceleratedCollisionConfig.enabled) {
            LOGGER.info("[NekoCore/Collision] Disabled via config.");
            return;
        }
        String override = System.getProperty("luminol.collision.backend", AcceleratedCollisionConfig.backend).toUpperCase();
        initByName(override);
    }

    public static String setBackend(String name) {
        String upper = name.toUpperCase();
        INativeCollisionBackend old = activeBackend;
        try { if (old != null) old.destroy(); } catch (Exception ignored) {}
        activeBackend = null;
        vanilla = false;
        initByName(upper);
        return upper.equals("VANILLA") ? "VANILLA" : (activeBackend != null ? activeBackend.getName() : "NONE");
    }

    public static String getCurrentBackendName() {
        if (vanilla) return "VANILLA";
        return activeBackend == null ? "DISABLED" : activeBackend.getName();
    }

    public static void reload() {
        INativeCollisionBackend old = activeBackend;
        try { if (old != null) old.destroy(); } catch (Exception ignored) {}
        activeBackend = null;
        vanilla = false;
        initialize();
    }

    private static void initByName(String upper) {
        switch (upper) {
            case "VANILLA" -> { LOGGER.info("[NekoCore/Collision] Using VANILLA (no acceleration)."); vanilla = true; }
            case "GPU"     -> tryInit(new GPUCollisionBackend());
            case "FFM"     -> tryInit(new FFMCollisionBackend());
            case "JAVA"    -> tryInit(new JavaCollisionBackend());
            default        -> autoSelect();
        }
    }

    private static void autoSelect() {
        for (INativeCollisionBackend b : new INativeCollisionBackend[]{
                new GPUCollisionBackend(), new FFMCollisionBackend(), new JavaCollisionBackend()}) {
            if (tryInit(b)) return;
        }
        LOGGER.warn("[NekoCore/Collision] All backends failed; collision acceleration disabled.");
    }

    private static boolean tryInit(INativeCollisionBackend b) {
        try {
            b.initialize();
            activeBackend = b;
            LOGGER.info("[NekoCore/Collision] Using backend: {}", b.getName());
            return true;
        } catch (Exception e) {
            LOGGER.warn("[NekoCore/Collision] Backend {} failed to init: {}", b.getName(), e.getMessage());
            return false;
        }
    }

    public static INativeCollisionBackend getActive() { return activeBackend; }
    public static boolean isVanilla() { return vanilla; }

    public static void destroy() {
        if (activeBackend != null) {
            activeBackend.destroy();
            activeBackend = null;
        }
    }
}
