package dev.micle.firefly_bush_backport.worldgen;

import dev.micle.firefly_bush_backport.FireflyBushBackport;
import dev.micle.firefly_bush_backport.block.ModBlocks;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderGetter;
import net.minecraft.core.Vec3i;
import net.minecraft.core.registries.Registries;
import net.minecraft.data.worldgen.BootstapContext;
import net.minecraft.data.worldgen.placement.PlacementUtils;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
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 net.minecraft.world.level.material.Fluids;

import java.util.List;

public class ModPlacedFeatures {
    public static final ResourceKey<PlacedFeature> PATCH_FIREFLY_BUSH_SWAMP_PLACED_KEY = registerKey("patch_firefly_bush_swamp");
    public static final ResourceKey<PlacedFeature> PATCH_FIREFLY_BUSH_NEAR_WATER_SWAMP_PLACED_KEY = registerKey("patch_firefly_bush_near_water_swamp");
    public static final ResourceKey<PlacedFeature> PATCH_FIREFLY_BUSH_NEAR_WATER_PLACED_KEY = registerKey("patch_firefly_bush_near_water");

    public static void bootstrap(BootstapContext<PlacedFeature> context) {
        HolderGetter<ConfiguredFeature<?, ?>> configuredFeatures = context.lookup(Registries.CONFIGURED_FEATURE);

        register(context, PATCH_FIREFLY_BUSH_SWAMP_PLACED_KEY, configuredFeatures.getOrThrow(ModConfiguredFeatures.PATCH_FIREFLY_BUSH_KEY), List.of(
                RarityFilter.onAverageOnceEvery(8),
                InSquarePlacement.spread(),
                PlacementUtils.HEIGHTMAP,
                BiomeFilter.biome()
        ));

        register(context, PATCH_FIREFLY_BUSH_NEAR_WATER_SWAMP_PLACED_KEY, configuredFeatures.getOrThrow(ModConfiguredFeatures.PATCH_FIREFLY_BUSH_KEY), List.of(
                CountPlacement.of(3),
                InSquarePlacement.spread(),
                PlacementUtils.HEIGHTMAP,
                BiomeFilter.biome(),
                BlockPredicateFilter.forPredicate(BlockPredicate.allOf(
                        BlockPredicate.matchesBlocks(Blocks.AIR),
                        BlockPredicate.wouldSurvive(ModBlocks.FIREFLY_BUSH.get().defaultBlockState(), Vec3i.ZERO),
                        BlockPredicate.anyOf(
                                BlockPredicate.matchesFluids(new Vec3i(1, -1, 0), List.of(Fluids.WATER, Fluids.FLOWING_WATER)),
                                BlockPredicate.matchesFluids(new Vec3i(-1, -1, 0), List.of(Fluids.WATER, Fluids.FLOWING_WATER)),
                                BlockPredicate.matchesFluids(new Vec3i(0, -1, 1), List.of(Fluids.WATER, Fluids.FLOWING_WATER)),
                                BlockPredicate.matchesFluids(new Vec3i(0, -1, -1), List.of(Fluids.WATER, Fluids.FLOWING_WATER))
                        )
                ))
        ));

        register(context, PATCH_FIREFLY_BUSH_NEAR_WATER_PLACED_KEY, configuredFeatures.getOrThrow(ModConfiguredFeatures.PATCH_FIREFLY_BUSH_KEY), List.of(
                CountPlacement.of(2),
                InSquarePlacement.spread(),
                HeightmapPlacement.onHeightmap(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES),
                BiomeFilter.biome(),
                BlockPredicateFilter.forPredicate(BlockPredicate.allOf(
                        BlockPredicate.matchesBlocks(Blocks.AIR),
                        BlockPredicate.wouldSurvive(ModBlocks.FIREFLY_BUSH.get().defaultBlockState(), Vec3i.ZERO),
                        BlockPredicate.anyOf(
                                BlockPredicate.matchesFluids(new Vec3i(1, -1, 0), List.of(Fluids.WATER, Fluids.FLOWING_WATER)),
                                BlockPredicate.matchesFluids(new Vec3i(-1, -1, 0), List.of(Fluids.WATER, Fluids.FLOWING_WATER)),
                                BlockPredicate.matchesFluids(new Vec3i(0, -1, 1), List.of(Fluids.WATER, Fluids.FLOWING_WATER)),
                                BlockPredicate.matchesFluids(new Vec3i(0, -1, -1), List.of(Fluids.WATER, Fluids.FLOWING_WATER))
                        )
                ))
        ));
    }

    private static ResourceKey<PlacedFeature> registerKey(String name) {
        return ResourceKey.create(Registries.PLACED_FEATURE, ResourceLocation.fromNamespaceAndPath(FireflyBushBackport.MOD_ID, name));
    }

    private static void register(BootstapContext<PlacedFeature> context, ResourceKey<PlacedFeature> key, Holder<ConfiguredFeature<?, ?>> configuration, List<PlacementModifier> modifiers) {
        context.register(key, new PlacedFeature(configuration, List.copyOf(modifiers)));
    }
}
