package net.halbear.aotg.registries;

import net.halbear.aotg.AgeoftheGods;
import net.minecraft.core.BlockPos;
import net.minecraft.core.HolderGetter;
import net.minecraft.core.registries.Registries;
import net.minecraft.data.worldgen.BootstrapContext;
import net.minecraft.data.worldgen.placement.PlacementUtils;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.level.levelgen.placement.*;

import java.util.List;

import static net.halbear.aotg.registries.ModConfiguredFeatures.*;

public class ModPlacedFeatures {
    public static final ResourceKey<PlacedFeature> TWISTY_TREE_PLACED_KEY =
            ResourceKey.create(Registries.PLACED_FEATURE, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "twisty_tree_placed"));
    public static final ResourceKey<PlacedFeature> SHORT_TWISTY_TREE_PLACED_KEY =
            ResourceKey.create(Registries.PLACED_FEATURE, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "short_maquis_twisty_tree_placed"));
    public static final ResourceKey<PlacedFeature> SHORT_GARRIGUE_TWISTY_TREE_PLACED_KEY =
            ResourceKey.create(Registries.PLACED_FEATURE, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "short_garrigue_twisty_tree_placed"));
    public static final ResourceKey<PlacedFeature> TALL_THIN_TWISTY_TREE_PLACED_KEY =
            ResourceKey.create(Registries.PLACED_FEATURE, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "tall_thin_twisty_tree_placed"));
    public static final ResourceKey<PlacedFeature> SHORT_THIN_TWISTY_TREE_PLACED_KEY =
            ResourceKey.create(Registries.PLACED_FEATURE, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "short_thin_twisty_tree_placed"));
    public static final ResourceKey<PlacedFeature> GRANITE_BOULDER_PLACED = ResourceKey.create(
            Registries.PLACED_FEATURE, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "granite_boulder_placed"));

    public static final ResourceKey<PlacedFeature> SHALE_BOULDER_PLACED = ResourceKey.create(
            Registries.PLACED_FEATURE, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "shale_boulder_placed"));

    public static final ResourceKey<PlacedFeature> GRAVEL_BOULDER_PLACED = ResourceKey.create(
            Registries.PLACED_FEATURE, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "gravel_boulder_placed"));
    public static final ResourceKey<PlacedFeature> LIMESTONE_BOULDER_PLACED = ResourceKey.create(
            Registries.PLACED_FEATURE, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "limestone_boulder_placed"));

    public static void bootstrap(BootstrapContext<PlacedFeature> context) {
        HolderGetter<ConfiguredFeature<?, ?>> configuredFeatures = context.lookup(Registries.CONFIGURED_FEATURE);
        var configuredTreeHolder = configuredFeatures.getOrThrow(TALL_THIN_TWISTY_TREE);

        context.register(TALL_THIN_TWISTY_TREE_PLACED_KEY, new PlacedFeature(
                configuredTreeHolder,
                List.of(
                        CountPlacement.of(15),
                        RarityFilter.onAverageOnceEvery(6),
                        InSquarePlacement.spread(),
                        PlacementUtils.HEIGHTMAP_OCEAN_FLOOR,
                        BlockPredicateFilter.forPredicate(
                                BlockPredicate.matchesBlocks(
                                        new BlockPos(0, -1, 0),
                                        ModBlocks.SHALE_GRASS_BLOCK.get(),
                                        Blocks.SANDSTONE,
                                        ModBlocks.SHALE_BLOCK.get(),
                                        ModBlocks.LIMESTONE_GRASS_BLOCK.get()
                                )
                        ),
                        SurfaceWaterDepthFilter.forMaxDepth(0),
                        BiomeFilter.biome()
                )
        ));
        configuredTreeHolder = configuredFeatures.getOrThrow(SHORT_THIN_TWISTY_TREE);

        context.register(SHORT_THIN_TWISTY_TREE_PLACED_KEY, new PlacedFeature(
                configuredTreeHolder,
                List.of(
                        CountPlacement.of(15),
                        RarityFilter.onAverageOnceEvery(6),
                        InSquarePlacement.spread(),
                        PlacementUtils.HEIGHTMAP_OCEAN_FLOOR,
                        BlockPredicateFilter.forPredicate(
                                BlockPredicate.matchesBlocks(
                                        new BlockPos(0, -1, 0),
                                        ModBlocks.SHALE_GRASS_BLOCK.get(),
                                        Blocks.SANDSTONE,
                                        ModBlocks.SHALE_BLOCK.get(),
                                        ModBlocks.LIMESTONE_GRASS_BLOCK.get()
                                )
                        ),
                        SurfaceWaterDepthFilter.forMaxDepth(2),
                        BiomeFilter.biome()
                )
        ));
        configuredTreeHolder = configuredFeatures.getOrThrow(ModConfiguredFeatures.TWISTY_TREE_KEY);
        context.register(TWISTY_TREE_PLACED_KEY, new PlacedFeature(
                configuredTreeHolder,
                List.of(
                        CountPlacement.of(7),
                        RarityFilter.onAverageOnceEvery(10),
                        InSquarePlacement.spread(),
                        PlacementUtils.HEIGHTMAP_OCEAN_FLOOR,
                        BlockPredicateFilter.forPredicate(
                                BlockPredicate.matchesBlocks(
                                        new BlockPos(0, -1, 0),
                                        ModBlocks.SHALE_GRASS_BLOCK.get(),
                                        Blocks.SANDSTONE,
                                        ModBlocks.SHALE_BLOCK.get(),
                                        ModBlocks.LIMESTONE_GRASS_BLOCK.get()
                                )
                        ),
                        SurfaceWaterDepthFilter.forMaxDepth(0),
                        BiomeFilter.biome()
                )
        ));
        configuredTreeHolder = configuredFeatures.getOrThrow(GARRIGUE_TWISTY_TREE);
        context.register(SHORT_GARRIGUE_TWISTY_TREE_PLACED_KEY, new PlacedFeature(
                configuredTreeHolder,
                List.of(
                        NoiseThresholdCountPlacement.of(-0.2D, 3, 10),
                        RarityFilter.onAverageOnceEvery(10),
                        InSquarePlacement.spread(),
                        PlacementUtils.HEIGHTMAP_OCEAN_FLOOR,
                        BlockPredicateFilter.forPredicate(
                                BlockPredicate.matchesBlocks(
                                        new BlockPos(0, -1, 0),
                                        ModBlocks.SHALE_GRASS_BLOCK.get(),
                                        Blocks.SANDSTONE,
                                        ModBlocks.SHALE_BLOCK.get(),
                                        ModBlocks.LIMESTONE_GRASS_BLOCK.get(),
                                        Blocks.SAND
                                )
                        ),
                        SurfaceWaterDepthFilter.forMaxDepth(0),
                        BiomeFilter.biome()
                )
        ));
        configuredTreeHolder = configuredFeatures.getOrThrow(ModConfiguredFeatures.MAQUIS_SHORT_TWISTY_TREE_KEY);
        context.register(SHORT_TWISTY_TREE_PLACED_KEY, new PlacedFeature(
                configuredTreeHolder,
                List.of(
                        NoiseThresholdCountPlacement.of(-0.1D, 3, 10),
                        RarityFilter.onAverageOnceEvery(10),
                        InSquarePlacement.spread(),
                        PlacementUtils.HEIGHTMAP_OCEAN_FLOOR,
                        BlockPredicateFilter.forPredicate(
                                BlockPredicate.matchesBlocks(
                                        new BlockPos(0, -1, 0),
                                        ModBlocks.SHALE_GRASS_BLOCK.get(),
                                        Blocks.SANDSTONE,
                                        Blocks.GRANITE,
                                        ModBlocks.SHALE_BLOCK.get(),
                                        ModBlocks.LIMESTONE_GRASS_BLOCK.get()
                                )
                        ),
                        SurfaceWaterDepthFilter.forMaxDepth(0),
                        BiomeFilter.biome()
                )
        ));

        var configuredLookup = context.lookup(Registries.CONFIGURED_FEATURE);
        var configuredHolder = configuredLookup.getOrThrow(GRANITE_BOULDER);

        List<PlacementModifier> modifiers = List.of(
                CountPlacement.of(1),
                InSquarePlacement.spread(),
                HeightmapPlacement.onHeightmap(Heightmap.Types.WORLD_SURFACE_WG),
                BlockPredicateFilter.forPredicate(
                        BlockPredicate.matchesBlocks(
                                new BlockPos(0, -1, 0),
                                Blocks.GRANITE
                        )
                ),
                BiomeFilter.biome()
        );

        context.register(GRANITE_BOULDER_PLACED, new PlacedFeature(configuredHolder, modifiers));
        configuredHolder = configuredLookup.getOrThrow(GRAVEL_BOULDER);
        context.register(GRAVEL_BOULDER_PLACED, new PlacedFeature(configuredHolder, modifiers));
        configuredHolder = configuredLookup.getOrThrow(SHALE_BOULDER);
        modifiers = List.of(
                CountPlacement.of(5),
                InSquarePlacement.spread(),
                HeightmapPlacement.onHeightmap(Heightmap.Types.WORLD_SURFACE_WG),
                BiomeFilter.biome()
        );
        context.register(SHALE_BOULDER_PLACED, new PlacedFeature(configuredHolder, modifiers));
        configuredHolder = configuredLookup.getOrThrow(LIMESTONE_BOULDER);
        modifiers = List.of(
                CountPlacement.of(3),
                InSquarePlacement.spread(),
                HeightmapPlacement.onHeightmap(Heightmap.Types.WORLD_SURFACE_WG),
                BiomeFilter.biome()
        );
        context.register(LIMESTONE_BOULDER_PLACED, new PlacedFeature(configuredHolder, modifiers));
    }
}
