package dev.micle.loginprotection.setup;

import com.google.common.collect.Lists;
import dev.micle.loginprotection.LoginProtection;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig;
import org.apache.commons.lang3.tuple.Pair;

import java.util.List;

@Mod.EventBusSubscriber(modid = LoginProtection.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
public final class Config {
    public static final Server SERVER;
    public static final ForgeConfigSpec SERVER_SPEC;
    static {
        Pair<Server, ForgeConfigSpec> spec_pair = new ForgeConfigSpec.Builder().configure(Server::new);
        SERVER = spec_pair.getLeft();
        SERVER_SPEC = spec_pair.getRight();
    }

    public static void init() {
        ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, SERVER_SPEC);
    }

    public static class Server {
        public static ForgeConfigSpec.BooleanValue POST_REFILL_AIR_ENABLED;
        public static ForgeConfigSpec.BooleanValue POST_WATER_ENABLED;
        public static ForgeConfigSpec.IntValue POST_WATER_DURATION;
        public static ForgeConfigSpec.BooleanValue POST_LAVA_ENABLED;
        public static ForgeConfigSpec.IntValue POST_LAVA_DURATION;
        public static ForgeConfigSpec.BooleanValue POST_FIRE_ENABLED;
        public static ForgeConfigSpec.IntValue POST_FIRE_DURATION;

        public static ForgeConfigSpec.BooleanValue LOGIN_MOBS_IGNORE_PLAYER;
        public static ForgeConfigSpec.BooleanValue LOGIN_APPLY_POST_EFFECTS;
        public static ForgeConfigSpec.ConfigValue<List<? extends String>> LOGIN_KEY_ALLOW_LIST;
        public static ForgeConfigSpec.BooleanValue LOGIN_GRACE_ENABLED;
        public static ForgeConfigSpec.BooleanValue LOGIN_GRACE_MOBS_IGNORE_PLAYER;
        public static ForgeConfigSpec.IntValue LOGIN_GRACE_DURATION;

        public static ForgeConfigSpec.BooleanValue AFK_PROTECTION_ENABLED;
        public static ForgeConfigSpec.IntValue AFK_TIME_THRESHOLD;
        public static ForgeConfigSpec.BooleanValue AFK_APPLY_POST_EFFECTS;
        public static ForgeConfigSpec.BooleanValue AFK_MOBS_IGNORE_PLAYER;
        public static ForgeConfigSpec.ConfigValue<List<? extends String>> AFK_KEY_ALLOW_LIST;
        public static ForgeConfigSpec.BooleanValue AFK_GRACE_ENABLED;
        public static ForgeConfigSpec.BooleanValue AFK_GRACE_MOBS_IGNORE_PLAYER;
        public static ForgeConfigSpec.IntValue AFK_GRACE_DURATION;

        Server(ForgeConfigSpec.Builder builder) {
            builder.comment("Settings for protecting players while they are joining.").push("Login");
            LOGIN_APPLY_POST_EFFECTS = builder
                    .comment("Whether to apply any post protection effects to joining players.")
                    .define("applyPostProtectionEffects", true);
            LOGIN_MOBS_IGNORE_PLAYER = builder
                    .comment("Whether mobs will ignore a protected player. (They will not attack/aggro)")
                    .define("mobsIgnorePlayer", true);
            builder.push("AllowedKeys");
            LOGIN_KEY_ALLOW_LIST = builder
                    .comment("Allowed keys players can press without becoming active.\n" +
                            "Available values: PAUSE, DEBUG, FULLSCREEN, PERSPECTIVE, SMOOTH_CAMERA, SCREENSHOT, SPECTATOR_OUTLINES,\n" +
                            "ADVANCEMENTS, PLAYER_LIST, CHAT, SOCIAL_INTERACTIONS, LOAD_HOTBAR_ACTIVATOR, SAVE_HOTBAR_ACTIVATOR,\n" +
                            "SWAP_ITEM, INVENTORY, HOTBAR, DROP_ITEM, USE_ITEM, PICK_BLOCK, ATTACK, MOVE, SNEAK, JUMP")
                    .defineList("allowedKeys", Lists.newArrayList(KEYS.PAUSE.toString(), KEYS.DEBUG.toString(), KEYS.FULLSCREEN.toString(), KEYS.PERSPECTIVE.toString(), KEYS.SMOOTH_CAMERA.toString(),
                            KEYS.SCREENSHOT.toString(), KEYS.SPECTATOR_OUTLINES.toString(), KEYS.ADVANCEMENTS.toString(), KEYS.PLAYER_LIST.toString(), KEYS.CHAT.toString(), KEYS.SOCIAL_INTERACTIONS.toString(),
                            KEYS.LOAD_HOTBAR_ACTIVATOR.toString(), KEYS.SAVE_HOTBAR_ACTIVATOR.toString(), KEYS.SWAP_ITEM.toString(), KEYS.HOTBAR.toString(), KEYS.PICK_BLOCK.toString()), o -> o instanceof String);
            builder.pop();
            builder.push("Grace");
            LOGIN_GRACE_ENABLED = builder
                    .comment("Whether a player receives a grace period after becoming active or not.")
                    .define("graceEnabled", true);
            LOGIN_GRACE_MOBS_IGNORE_PLAYER = builder
                    .comment("Whether mobs ignore the player during their grace period.")
                    .define("graceMobsIgnorePlayer", true);
            LOGIN_GRACE_DURATION = builder
                    .comment("How long the grace period lasts in seconds.")
                    .defineInRange("graceDuration", 10, 1, Integer.MAX_VALUE);
            builder.pop();
            builder.pop();

            builder.comment("Settings for protecting players that are afk.").push("AFK");
            AFK_PROTECTION_ENABLED = builder
                    .comment("Enable protection of afk players?")
                    .define("enabled", true);
            AFK_TIME_THRESHOLD = builder
                    .comment("How long a player needs to be afk to become protected. (seconds)")
                    .defineInRange("timeThreshold", 600, 1, Integer.MAX_VALUE/20);
            AFK_APPLY_POST_EFFECTS = builder
                    .comment("Whether to apply any post protection effects to afk players.")
                    .define("applyPostProtectionEffects", false);
            AFK_MOBS_IGNORE_PLAYER = builder
                    .comment("Whether mobs will ignore a protected player. (They will not attack/aggro")
                    .define("mobsIgnorePlayerEnabled", true);
            builder.push("AllowedKeys");
            AFK_KEY_ALLOW_LIST = builder
                    .comment("Allowed keys players can press without becoming active.\n" +
                            "Available values: PAUSE, DEBUG, FULLSCREEN, PERSPECTIVE, SMOOTH_CAMERA, SCREENSHOT, SPECTATOR_OUTLINES,\n" +
                            "ADVANCEMENTS, PLAYER_LIST, CHAT, SOCIAL_INTERACTIONS, LOAD_HOTBAR_ACTIVATOR, SAVE_HOTBAR_ACTIVATOR,\n" +
                            "SWAP_ITEM, INVENTORY, HOTBAR, DROP_ITEM, USE_ITEM, PICK_BLOCK, ATTACK, MOVE, SNEAK, JUMP")
                    .defineList("allowedKeys", Lists.newArrayList(KEYS.PAUSE.toString(), KEYS.FULLSCREEN.toString(), KEYS.SCREENSHOT.toString(), KEYS.ADVANCEMENTS.toString()), o -> o instanceof String);
            builder.pop();
            builder.push("Grace");
            AFK_GRACE_ENABLED = builder
                    .comment("Whether a player receives a grace period after becoming active or not.")
                    .define("graceEnabled", false);
            AFK_GRACE_MOBS_IGNORE_PLAYER = builder
                    .comment("Whether mobs ignore the player during their grace period.")
                    .define("graceMobsIgnorePlayer", true);
            AFK_GRACE_DURATION = builder
                    .comment("How long the grace period lasts in seconds.")
                    .defineInRange("graceDuration", 5, 1, Integer.MAX_VALUE);
            builder.pop();
            builder.pop();

            builder.comment("Additional protection settings that apply as soon as a player becomes active if enabled.").push("Post");
            builder.push("WaterProtection");
            POST_REFILL_AIR_ENABLED = builder
                    .comment("Whether a player's air supply gets refilled.")
                    .define("refillAir", true);
            POST_WATER_ENABLED = builder
                    .comment("Whether a player receives water breathing when in water.")
                    .define("waterEnabled", false);
            POST_WATER_DURATION = builder
                    .comment("Water breathing duration in seconds.")
                    .defineInRange("waterDuration", 10, 1, Integer.MAX_VALUE/20);
            builder.pop();
            builder.push("LavaProtection");
            POST_LAVA_ENABLED = builder
                    .comment("Whether a player receives fire resistance when in lava.")
                    .define("enabled", true);
            POST_LAVA_DURATION = builder
                    .comment("Fire resistance duration in seconds.")
                    .defineInRange("duration", 10, 1, Integer.MAX_VALUE/20);
            builder.pop();
            builder.push("FireProtection");
            POST_FIRE_ENABLED = builder
                    .comment("Whether a player receives fire resistance when on fire.")
                    .define("enabled", false);
            POST_FIRE_DURATION = builder
                    .comment("Fire resistance duration in seconds.")
                    .defineInRange("duration", 10, 1, Integer.MAX_VALUE/20);
            builder.pop();
            builder.pop();
        }

        public enum KEYS {
            PAUSE,
            DEBUG,
            FULLSCREEN,
            PERSPECTIVE,
            SMOOTH_CAMERA,
            SCREENSHOT,
            SPECTATOR_OUTLINES,
            ADVANCEMENTS,
            PLAYER_LIST,
            CHAT,
            SOCIAL_INTERACTIONS,
            LOAD_HOTBAR_ACTIVATOR,
            SAVE_HOTBAR_ACTIVATOR,
            SWAP_ITEM,
            INVENTORY,
            HOTBAR,
            DROP_ITEM,
            USE_ITEM,
            PICK_BLOCK,
            ATTACK,
            MOVE,
            SNEAK,
            JUMP
        }
    }
}