package me.km.world;

import java.util.Map;
import me.km.blocks.ModBlocks;
import me.km.utils.ReflectionUtils;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.NetherBiome;
import net.minecraft.world.gen.GenerationStage;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.feature.DecoratedFeatureConfig;
import net.minecraft.world.gen.feature.Feature;
import net.minecraft.world.gen.feature.IFeatureConfig;
import net.minecraft.world.gen.feature.NoFeatureConfig;
import net.minecraft.world.gen.feature.OreFeatureConfig;
import net.minecraft.world.gen.feature.structure.StrongholdStructure;
import net.minecraft.world.gen.feature.structure.Structure;
import net.minecraft.world.gen.placement.CountRangeConfig;
import net.minecraft.world.gen.placement.Placement;
import net.minecraftforge.registries.ForgeRegistries;

public class ModWorldGeneration {
    public static void register() {
        // search for all biomes which generate ore
        StrongholdStructure patch = new StrongholdStructure(NoFeatureConfig::deserialize);
        for(Biome biome : ForgeRegistries.BIOMES.getValues()) {
            if(!(biome instanceof NetherBiome)) {
                biome.getCarvers(GenerationStage.Carving.AIR).clear();
                biome.getCarvers(GenerationStage.Carving.LIQUID).clear();
            }
            Map<Structure<?>, IFeatureConfig> map = ReflectionUtils.getBiomeStructures(biome);
            if(map.remove(Feature.STRONGHOLD) != null) {
                System.out.println("removing stronghold from " + biome.getTranslationKey());
            }
            for(ConfiguredFeature f : biome.getFeatures(GenerationStage.Decoration.UNDERGROUND_ORES)) {
                if(!(f.config instanceof DecoratedFeatureConfig)) {
                    continue;
                }
                DecoratedFeatureConfig conf = (DecoratedFeatureConfig) f.config;
                if(!(conf.feature.config instanceof OreFeatureConfig)) {
                    continue;
                }
                OreFeatureConfig ore = (OreFeatureConfig) conf.feature.config;
                if(ore.state == Blocks.IRON_ORE.getDefaultState()) {
                    addFeatures(biome);
                    break;
                }
            }
        }
    }

    private static void addOre(Biome b, Block ore, int maxCount, int spawnTries, int maxHeight) {
        b.addFeature(GenerationStage.Decoration.UNDERGROUND_ORES,
                Feature.ORE.withConfiguration(new OreFeatureConfig(OreFeatureConfig.FillerBlockType.NATURAL_STONE,
                        ore.getDefaultState(), maxCount)
                ).withPlacement(Placement.COUNT_RANGE.configure(new CountRangeConfig(spawnTries, 0, 0, maxHeight))));
    }

    private static void addFeatures(Biome biome) {
        //          | max   | bottom | top    | max  | spawn |
        // name     | size  | offset | offset | high | tries |
        // ---------------------------------------------------
        // coal     |    17 |      0 |      0 |  128 |    20 |
        // iron     |     9 |      0 |      0 |   64 |    20 |
        // gold     |     9 |      0 |      0 |   32 |     2 |
        // redstone |     8 |      0 |      0 |   16 |     8 |
        // diamond  |     8 |      0 |      0 |   16 |     1 |
        // lapis    |     7 |      - |      - |    - |     - |
        // copper   |     9 |      0 |      0 |  128 |    25 |
        // tin      |     6 |      0 |      0 |   96 |    12 |
        // silver   |     9 |      0 |      0 |   64 |     3 |

        addOre(biome, ModBlocks.copperOre, 9, 25, 128);
        addOre(biome, ModBlocks.tinOre, 6, 12, 96);
        addOre(biome, ModBlocks.silverOre, 9, 3, 64);
    }
}
