package land.chipmunk.chipmunkmod;

import land.chipmunk.chipmunkmod.config.ChipmunkModMigrations;
import land.chipmunk.chipmunkmod.config.Configuration;
import land.chipmunk.chipmunkmod.modules.SelfCare;
import land.chipmunk.chipmunkmod.util.configurate.ConfigurateUtilities;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.loader.api.FabricLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongepowered.configurate.BasicConfigurationNode;
import org.spongepowered.configurate.gson.GsonConfigurationLoader;
import org.spongepowered.configurate.objectmapping.ObjectMapper;
import org.spongepowered.configurate.util.NamingSchemes;

import java.io.IOException;
import java.nio.file.Path;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ChipmunkMod implements ModInitializer {
    public static final Logger LOGGER = LoggerFactory.getLogger("ChipmunkMod");
    private static final Path CONFIG_PATH = FabricLoader.getInstance()
            .getConfigDir().resolve("chipmunkmod.json");
    public static Configuration CONFIG;

    public static ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

    public static Configuration loadConfig () throws IOException {
        final ChipmunkModMigrations migrations = new ChipmunkModMigrations();
        final ObjectMapper.Factory customFactory = ObjectMapper.factoryBuilder()
                .defaultNamingScheme(NamingSchemes.CAMEL_CASE)
                .build();

        final GsonConfigurationLoader loader = GsonConfigurationLoader.builder()
                .defaultOptions(options -> options
                        .serializers(build -> build
                                .registerAnnotatedObjects(customFactory)
                                .registerAll(ConfigurateUtilities.customSerializers()))
                        .shouldCopyDefaults(true))
                .indent(4)
                .path(CONFIG_PATH)
                .build();

        // Configurate will create parent directories for us, so we don't need to do it
        final BasicConfigurationNode node = loader.load();
        if (node.empty()) { // Config empty, fill it with defaults
            final Configuration defaults = new Configuration();
            node.set(Configuration.class, defaults);
            migrations.setLatest(node);
            loader.save(node);

            return defaults;
        }

        if (migrations.migrate(node)) { // Migrated, write new config
            loader.save(node);
        }

        return node.get(Configuration.class);
    }

    @Override
    public void onInitialize () {
        // This code runs as soon as Minecraft is in a mod-load-ready state.
        // However, some things (like resources) may still be uninitialized.
        // Proceed with mild caution.

        try {
            CONFIG = loadConfig();
        } catch (final IOException exception) {
            throw new RuntimeException("Could not load the config", exception);
        }

        SelfCare.INSTANCE.init();

        LOGGER.info("Loaded ChipmunkMod (chayapak's fork)");
    }
}
