/*
 * This file is part of Terra.
 *
 * Terra is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Terra is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Terra.  If not, see <https://www.gnu.org/licenses/>.
 */

package com.dfsek.terra.forge;

import ca.solostudios.strata.Versions;
import ca.solostudios.strata.parser.tokenizer.ParseException;
import ca.solostudios.strata.version.Version;
import net.minecraft.MinecraftVersion;
import net.minecraft.registry.Registry;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.source.MultiNoiseBiomeSourceParameterList;
import net.minecraft.world.dimension.DimensionType;
import net.minecraft.world.gen.chunk.ChunkGeneratorSettings;
import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.server.ServerLifecycleHooks;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import com.dfsek.terra.addon.EphemeralAddon;
import com.dfsek.terra.api.addon.BaseAddon;
import com.dfsek.terra.api.util.generic.Lazy;
import com.dfsek.terra.mod.CommonPlatform;
import com.dfsek.terra.mod.ModPlatform;
import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper;


public class ForgePlatform extends ModPlatform {
    private static final Logger LOGGER = LoggerFactory.getLogger(ForgePlatform.class);
    private final Lazy<File> dataFolder = Lazy.lazy(() -> new File("./config/Terra"));

    public ForgePlatform() {
        CommonPlatform.initialize(this);
        load();
    }

    @Override
    public MinecraftServer getServer() {
        return ServerLifecycleHooks.getCurrentServer();
    }

    @Override
    public boolean reload() {
        getTerraConfig().load(this);
        getRawConfigRegistry().clear();
        boolean succeed = getRawConfigRegistry().loadAll(this);

        MinecraftServer server = getServer();

        if(server != null) {
            server.reloadResources(server.getDataPackManager().getNames()).exceptionally(throwable -> {
                LOGGER.warn("Failed to execute reload", throwable);
                return null;
            }).join();
            //BiomeUtil.registerBiomes();
            server.getWorlds().forEach(world -> {
                if(world.getChunkManager().getChunkGenerator() instanceof MinecraftChunkGeneratorWrapper chunkGeneratorWrapper) {
                    getConfigRegistry().get(chunkGeneratorWrapper.getPack().getRegistryKey()).ifPresent(pack -> {
                        chunkGeneratorWrapper.setPack(pack);
                        LOGGER.info("Replaced pack in chunk generator for world {}", world);
                    });
                }
            });
        }
        return succeed;
    }

    @Override
    protected Iterable<BaseAddon> platformAddon() {
        List<BaseAddon> addons = new ArrayList<>();

        super.platformAddon().forEach(addons::add);

        String mcVersion = MinecraftVersion.CURRENT.getName();
        try {
            addons.add(new EphemeralAddon(Versions.parseVersion(mcVersion), "minecraft"));
        } catch(ParseException e) {
            try {
                addons.add(new EphemeralAddon(Versions.parseVersion(mcVersion + ".0"), "minecraft"));
            } catch(ParseException ex) {
                LOGGER.warn("Failed to parse Minecraft version", e);
            }
        }

        FMLLoader.getLoadingModList().getMods().forEach(mod -> {
            String id = mod.getModId();
            if(id.equals("terra") || id.equals("minecraft") || id.equals("java")) return;
            Version version = Versions.getVersion(mod.getVersion().getMajorVersion(), mod.getVersion().getMinorVersion(),
                mod.getVersion().getIncrementalVersion());
            addons.add(new EphemeralAddon(version, "forge:" + id));
        });

        return addons;
    }

    @Override
    public @NotNull String platformName() {
        return "Forge";
    }

    @Override
    public @NotNull File getDataFolder() {
        return dataFolder.value();
    }

    @Override
    public BaseAddon getPlatformAddon() {
        return new ForgeAddon(this);
    }

    @Override
    public Registry<DimensionType> dimensionTypeRegistry() {
        return null;
    }

    @Override
    public Registry<Biome> biomeRegistry() {
        return null;
    }

    @Override
    public Registry<ChunkGeneratorSettings> chunkGeneratorSettingsRegistry() {
        return null;
    }

    @Override
    public Registry<MultiNoiseBiomeSourceParameterList> multiNoiseBiomeSourceParameterListRegistry() {
        return null;
    }
}
