package dev.micle.firefly_bush_backport.config;

import dev.micle.firefly_bush_backport.FireflyBushBackport;
import net.minecraft.util.random.SimpleWeightedRandomList;
import net.minecraft.world.level.Level;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.config.ModConfigEvent;
import org.apache.commons.lang3.tuple.Pair;

import java.awt.*;
import java.util.List;

@Mod.EventBusSubscriber(modid = FireflyBushBackport.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
public final class Config {
    public static final Client CLIENT;
    public static final ForgeConfigSpec CLIENT_SPEC;
    public static final Common COMMON;
    public static final ForgeConfigSpec COMMON_SPEC;
    public static final Server SERVER;
    public static final ForgeConfigSpec SERVER_SPEC;

    static {
        Pair<Client, ForgeConfigSpec> clientSpecPair = new ForgeConfigSpec.Builder().configure(Client::new);
        CLIENT = clientSpecPair.getLeft();
        CLIENT_SPEC = clientSpecPair.getRight();

        Pair<Common, ForgeConfigSpec> commonSpecPair = new ForgeConfigSpec.Builder().configure(Common::new);
        COMMON = commonSpecPair.getLeft();
        COMMON_SPEC = commonSpecPair.getRight();

        Pair<Server, ForgeConfigSpec> serverSpecPair = new ForgeConfigSpec.Builder().configure(Server::new);
        SERVER = serverSpecPair.getLeft();
        SERVER_SPEC = serverSpecPair.getRight();
    }

    public static void register() {
        FireflyBushBackport.getFMLJavaModLoadingContext().registerConfig(ModConfig.Type.CLIENT, CLIENT_SPEC);
        FireflyBushBackport.getFMLJavaModLoadingContext().registerConfig(ModConfig.Type.COMMON, COMMON_SPEC);
        FireflyBushBackport.getFMLJavaModLoadingContext().registerConfig(ModConfig.Type.SERVER, SERVER_SPEC);
    }

    @SubscribeEvent
    public static void onConfigReloadEvent(ModConfigEvent event) {
        if (event.getConfig().getSpec() == CLIENT_SPEC) {
            Client.onConfigReload();
        } else if (event.getConfig().getSpec() == COMMON_SPEC) {
            Common.onConfigReload();
        } else if (event.getConfig().getSpec() == SERVER_SPEC) {
            Server.onConfigReload();
        }
    }

    public static class Client {
        public static ForgeConfigSpec.DoubleValue bushFireflyChancePerTick;
        public static ForgeConfigSpec.DoubleValue bushFireflyHorizontalRange;
        public static ForgeConfigSpec.DoubleValue bushFireflyVerticalRange;
        public static ForgeConfigSpec.IntValue bushFireflySpawnMaxBrightnessLevel;
        public static ForgeConfigSpec.IntValue bushFireflyAmbientSoundChanceOneIn;

        public static ForgeConfigSpec.BooleanValue bushExtraAlwaysPlayAmbientSound;
        public static ForgeConfigSpec.BooleanValue bushExtraAlwaysSpawnParticles;

        public static ForgeConfigSpec.DoubleValue particleFadeOutLightTime;
        public static ForgeConfigSpec.DoubleValue particleFadeInLightTime;
        public static ForgeConfigSpec.DoubleValue particleFadeOutAlphaTime;
        public static ForgeConfigSpec.DoubleValue particleFadeInAlphaTime;
        public static ForgeConfigSpec.IntValue particleMinLifetime;
        public static ForgeConfigSpec.IntValue particleMaxLifetime;

        public static ForgeConfigSpec.DoubleValue particleExtraFriction;
        public static ForgeConfigSpec.DoubleValue particleExtraScale;
        public static ForgeConfigSpec.DoubleValue particleExtraBrightness;
        private static ForgeConfigSpec.ConfigValue<List<? extends String>> particleExtraColors;
        public static SimpleWeightedRandomList<Color> particleExtraColorsWeightedList;

        Client(ForgeConfigSpec.Builder builder) {
            builder.comment("Settings for the firefly bush.").push("bush");
            bushFireflyChancePerTick = builder
                    .defineInRange("bushFireflyChancePerTick", 0.7, 0, 1);
            bushFireflyHorizontalRange = builder
                    .defineInRange("bushFireflyHorizontalRange", 10.0, 0, Double.MAX_VALUE);
            bushFireflyVerticalRange = builder
                    .defineInRange("bushFireflyVerticalRange", 5.0, 0, Double.MAX_VALUE);
            bushFireflySpawnMaxBrightnessLevel = builder
                    .defineInRange("bushFireflySpawnMaxBrightnessLevel", 13, 0, Level.MAX_BRIGHTNESS);
            bushFireflyAmbientSoundChanceOneIn = builder
                    .defineInRange("bushFireflyAmbientSoundChanceOneIn", 30, 0, Integer.MAX_VALUE);

            builder.comment("Extra settings for the firefly bush.").push("extra");
            bushExtraAlwaysPlayAmbientSound = builder
                    .define("bushExtraAlwaysPlayAmbientSound", false);
            bushExtraAlwaysSpawnParticles = builder
                    .define("bushExtraAlwaysSpawnParticles", false);
            builder.pop();
            builder.pop();

            builder.comment("Settings for the firefly particle.").push("particle");
            particleFadeOutLightTime = builder
                    .defineInRange("particleFadeOutLightTime", 0.3, 0, 1.0);
            particleFadeInLightTime = builder
                    .defineInRange("particleFadeInLightTime", 0.1, 0, 1.0);
            particleFadeOutAlphaTime = builder
                    .defineInRange("particleFadeOutAlphaTime", 0.5, 0, 1.0);
            particleFadeInAlphaTime = builder
                    .defineInRange("particleFadeInAlphaTime", 0.3, 0, 1.0);
            particleMinLifetime = builder
                    .defineInRange("particleMinLifetime", 36, 0, Integer.MAX_VALUE);
            particleMaxLifetime = builder
                    .defineInRange("particleMaxLifetime", 180, 0, Integer.MAX_VALUE);

            builder.comment("Extra settings for the firefly particle.").push("extra");
            particleExtraFriction = builder
                    .defineInRange("particleExtraFriction", 0.96, 0, Double.MAX_VALUE);
            particleExtraScale = builder
                    .defineInRange("particleExtraScale", 0.75, 0, Double.MAX_VALUE);
            particleExtraBrightness = builder
                    .defineInRange("particleExtraBrightness", 255.0, 0, 255);
            particleExtraColors = builder
                    .comment("List of color hex values and their weight. Format: '<color_hex>,<weight>'")
                    .defineList("particleExtraColors", List.of("#ffffff,1"), Client::isValidColorEntry);
            builder.pop();
            builder.pop();
        }

        private static void onConfigReload() {
            SimpleWeightedRandomList.Builder<Color> particleExtraColorsWeightedListBuilder = SimpleWeightedRandomList.builder();
            for (String entry : particleExtraColors.get()) {
                String[] splitEntry = entry.split(",");
                particleExtraColorsWeightedListBuilder.add(Color.decode(splitEntry[0]), Integer.parseInt(splitEntry[1]));
            }
            particleExtraColorsWeightedList = particleExtraColorsWeightedListBuilder.build();
        }

        private static boolean isValidColorEntry(Object entry) {
            return entry instanceof String && ((String) entry).matches("#\\w{6},\\d+$");
        }
    }

    public static class Common {
        Common(ForgeConfigSpec.Builder builder) {}

        private static void onConfigReload() {}
    }

    public static class Server {
        Server(ForgeConfigSpec.Builder builder) {}

        private static void onConfigReload() {}
    }
}
