package net.halbear.aotg.registries;

import net.halbear.aotg.AgeoftheGods;
import net.halbear.aotg.custom.WorldGen.GenerationFeatures.*;
import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.Registries;
import net.minecraft.data.worldgen.BootstrapContext;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.tags.BlockTags;
import net.minecraft.util.valueproviders.ConstantInt;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.configurations.BlockBlobConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.TreeConfiguration;
import net.minecraft.world.level.levelgen.feature.featuresize.TwoLayersFeatureSize;
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;
import net.minecraft.world.level.levelgen.structure.templatesystem.TagMatchTest;
import net.neoforged.fml.common.Mod;

import java.util.List;

public class ModConfiguredFeatures {
    public static final ResourceKey<ConfiguredFeature<?, ?>> PINE_TREE =
            ResourceKey.create(Registries.CONFIGURED_FEATURE, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "pine_tree"));
    public static final ResourceKey<ConfiguredFeature<?, ?>> TWISTY_TREE_KEY =
            ResourceKey.create(Registries.CONFIGURED_FEATURE, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "maquis_tall_twisty_tree"));
    public static final ResourceKey<ConfiguredFeature<?, ?>> MAQUIS_SHORT_TWISTY_TREE_KEY =
            ResourceKey.create(Registries.CONFIGURED_FEATURE, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "maquis_short_twisty_tree"));
    public static final ResourceKey<ConfiguredFeature<?, ?>> GARRIGUE_TWISTY_TREE =
            ResourceKey.create(Registries.CONFIGURED_FEATURE, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "garrigue_short_twisty_tree"));
    public static final ResourceKey<ConfiguredFeature<?, ?>> TALL_THIN_TWISTY_TREE =
            ResourceKey.create(Registries.CONFIGURED_FEATURE, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "tall_thin_twisty_tree"));
    public static final ResourceKey<ConfiguredFeature<?, ?>> TALL_THIN_BIRCH_TREE =
            ResourceKey.create(Registries.CONFIGURED_FEATURE, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "tall_thin_birch_tree"));
    public static final ResourceKey<ConfiguredFeature<?, ?>> SHORT_THIN_TWISTY_TREE =
            ResourceKey.create(Registries.CONFIGURED_FEATURE, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "short_thin_twisty_tree"));

    public static final ResourceKey<ConfiguredFeature<?, ?>> GRANITE_BOULDER = ResourceKey.create(
            Registries.CONFIGURED_FEATURE, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "granite_boulder"));
    public static final ResourceKey<ConfiguredFeature<?, ?>> SHALE_BOULDER = ResourceKey.create(
            Registries.CONFIGURED_FEATURE, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "shale_boulder"));
    public static final ResourceKey<ConfiguredFeature<?, ?>> GRAVEL_BOULDER = ResourceKey.create(
            Registries.CONFIGURED_FEATURE, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "gravel_boulder"));
    public static final ResourceKey<ConfiguredFeature<?, ?>> LIMESTONE_BOULDER = ResourceKey.create(
            Registries.CONFIGURED_FEATURE, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "limestone_boulder"));

    public static final ResourceKey<ConfiguredFeature<?, ?>> SILVER_ORE_CONF =
            ResourceKey.create(Registries.CONFIGURED_FEATURE, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "silver_ore_conf"));
    public static final ResourceKey<ConfiguredFeature<?, ?>> ZINC_ORE_CONF =
            ResourceKey.create(Registries.CONFIGURED_FEATURE, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "zinc_ore_conf"));
    public static final ResourceKey<ConfiguredFeature<?, ?>> TIN_ORE_CONF =
            ResourceKey.create(Registries.CONFIGURED_FEATURE, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "tin_ore_conf"));


    public static void bootstrap(BootstrapContext<ConfiguredFeature<?, ?>> context) {
        List<OreConfiguration.TargetBlockState> Silver_ore_Targets = List.of(
                OreConfiguration.target(new TagMatchTest(BlockTags.STONE_ORE_REPLACEABLES), ModBlocks.SILVER_ORE.get().defaultBlockState()),
                OreConfiguration.target(new TagMatchTest(BlockTags.DEEPSLATE_ORE_REPLACEABLES), ModBlocks.SILVER_DEEPSLATE_ORE.get().defaultBlockState())
        );

        context.register(SILVER_ORE_CONF,
                new ConfiguredFeature<>(Feature.ORE, new OreConfiguration(Silver_ore_Targets, 7)));
        List<OreConfiguration.TargetBlockState> Tin_Ore_targets = List.of(
                OreConfiguration.target(new TagMatchTest(BlockTags.STONE_ORE_REPLACEABLES), ModBlocks.TIN_ORE.get().defaultBlockState()),
                OreConfiguration.target(new TagMatchTest(BlockTags.DEEPSLATE_ORE_REPLACEABLES), ModBlocks.TIN_DEEPSLATE_ORE.get().defaultBlockState())
        );

        context.register(TIN_ORE_CONF,
                new ConfiguredFeature<>(Feature.ORE, new OreConfiguration(Tin_Ore_targets, 7)));
        List<OreConfiguration.TargetBlockState> Zinc_ore_targets = List.of(
                OreConfiguration.target(new TagMatchTest(BlockTags.STONE_ORE_REPLACEABLES), ModBlocks.ZINC_ORE.get().defaultBlockState()),
                OreConfiguration.target(new TagMatchTest(BlockTags.DEEPSLATE_ORE_REPLACEABLES), ModBlocks.ZINC_DEEPSLATE_ORE.get().defaultBlockState())
        );

        context.register(ZINC_ORE_CONF,
                new ConfiguredFeature<>(Feature.ORE, new OreConfiguration(Zinc_ore_targets, 7)));


        context.register(PINE_TREE, new ConfiguredFeature<>(
                Feature.TREE,
                new TreeConfiguration.TreeConfigurationBuilder(
                        BlockStateProvider.simple(Blocks.SPRUCE_LOG.defaultBlockState()),
                        new PineTreeTrunkPlacer(21, 4, 5),
                        BlockStateProvider.simple(Blocks.SPRUCE_LEAVES.defaultBlockState()),
                        new PineTreeFoliagePlacer(ConstantInt.of(1),ConstantInt.of(0)),
                        new TwoLayersFeatureSize(3, 1, 3)
                ).build()
        ));
        context.register(SHORT_THIN_TWISTY_TREE, new ConfiguredFeature<>(
                Feature.TREE,
                new TreeConfiguration.TreeConfigurationBuilder(
                        BlockStateProvider.simple(ModBlocks.OLIVE_LOG.get().defaultBlockState()),
                        new ThinShortTwistyBranchingTrunkPlacer(5, 4, 5),
                        BlockStateProvider.simple(ModBlocks.OLIVE_LEAVES.get().defaultBlockState()),
                        new LeafBunchFoliagePlacer(ConstantInt.of(1),ConstantInt.of(0)),
                        new TwoLayersFeatureSize(3, 1, 3)
                ).build()
        ));
        context.register(TALL_THIN_BIRCH_TREE, new ConfiguredFeature<>(
                Feature.TREE,
                new TreeConfiguration.TreeConfigurationBuilder(
                        BlockStateProvider.simple(Blocks.BIRCH_LOG.defaultBlockState()),
                        new ThinTwistyBranchingTrunkPlacer(15, 10, 10),
                        BlockStateProvider.simple(Blocks.BIRCH_LEAVES.defaultBlockState()),
                        new LeafBunchFoliagePlacer(ConstantInt.of(1),ConstantInt.of(0)),
                        new TwoLayersFeatureSize(3, 1, 3)
                ).build()
        ));
        context.register(TALL_THIN_TWISTY_TREE, new ConfiguredFeature<>(
                Feature.TREE,
                new TreeConfiguration.TreeConfigurationBuilder(
                        BlockStateProvider.simple(ModBlocks.OLIVE_LOG.get().defaultBlockState()),
                        new ThinTwistyBranchingTrunkPlacer(12, 10, 10),
                        BlockStateProvider.simple(ModBlocks.OLIVE_LEAVES.get().defaultBlockState()),
                        new LeafBunchFoliagePlacer(ConstantInt.of(1),ConstantInt.of(0)),
                        new TwoLayersFeatureSize(3, 1, 3)
                ).build()
        ));
        context.register(TWISTY_TREE_KEY, new ConfiguredFeature<>(
                Feature.TREE,
                new TreeConfiguration.TreeConfigurationBuilder(
                        BlockStateProvider.simple(Blocks.OAK_LOG.defaultBlockState()),
                        new TwistyBranchingTrunkPlacer(15, 15, 15),
                        BlockStateProvider.simple(Blocks.OAK_LEAVES.defaultBlockState()),
                        new LeafBunchFoliagePlacer(ConstantInt.of(1),ConstantInt.of(0)),
                        new TwoLayersFeatureSize(5, 3, 5)
                ).build()
        ));
        context.register(GARRIGUE_TWISTY_TREE, new ConfiguredFeature<>(
                Feature.TREE,
                new TreeConfiguration.TreeConfigurationBuilder(
                        BlockStateProvider.simple(ModBlocks.OLIVE_LOG.get().defaultBlockState()),
                        new BushTwistyBranchingTrunkPlacer(2, 3, 3),
                        BlockStateProvider.simple(ModBlocks.OLIVE_LEAVES.get().defaultBlockState()),
                        new LeafBunchFoliagePlacer(ConstantInt.of(1),ConstantInt.of(0)),
                        new TwoLayersFeatureSize(3, 1, 3)
                ).build()
        ));
        context.register(MAQUIS_SHORT_TWISTY_TREE_KEY, new ConfiguredFeature<>(
                Feature.TREE,
                new TreeConfiguration.TreeConfigurationBuilder(
                        BlockStateProvider.simple(Blocks.OAK_LOG.defaultBlockState()),
                        new ThinTwistyBranchingTrunkPlacer(3, 3, 3),
                        BlockStateProvider.simple(Blocks.OAK_LEAVES.defaultBlockState()),
                        new LeafBunchFoliagePlacer(ConstantInt.of(1),ConstantInt.of(0)),
                        new TwoLayersFeatureSize(5, 3, 5)
                ).build()
        ));
        BlockBlobConfiguration config = new BlockBlobConfiguration(
                Blocks.GRANITE.defaultBlockState(),
                BlockPredicate.matchesBlocks(
                        new BlockPos(0, -1, 0),
                        ModBlocks.SHALE_GRASS_BLOCK.get(),
                        Blocks.SANDSTONE,
                        ModBlocks.SHALE_BLOCK.get(),
                        ModBlocks.LIMESTONE_GRASS_BLOCK.get()
                )
        );

        context.register(GRANITE_BOULDER, new ConfiguredFeature<>(Feature.BLOCK_BLOB, config));

        config = new BlockBlobConfiguration(
                ModBlocks.SHALE_BLOCK.get().defaultBlockState(),
                BlockPredicate.matchesBlocks(
                        new BlockPos(0, -1, 0),
                        ModBlocks.SHALE_GRASS_BLOCK.get(),
                        Blocks.SANDSTONE,
                        ModBlocks.SHALE_BLOCK.get(),
                        ModBlocks.LIMESTONE_GRASS_BLOCK.get()
                )
        );

        context.register(SHALE_BOULDER, new ConfiguredFeature<>(Feature.BLOCK_BLOB, config));
        config = new BlockBlobConfiguration(
                Blocks.GRAVEL.defaultBlockState(),
                BlockPredicate.matchesBlocks(
                        new BlockPos(0, -1, 0),
                        ModBlocks.SHALE_GRASS_BLOCK.get(),
                        Blocks.SANDSTONE,
                        ModBlocks.SHALE_BLOCK.get(),
                        ModBlocks.LIMESTONE_GRASS_BLOCK.get()
                )
        );

        context.register(GRAVEL_BOULDER, new ConfiguredFeature<>(Feature.BLOCK_BLOB, config));

        config = new BlockBlobConfiguration(
                ModBlocks.LIMESTONE_BLOCK.get().defaultBlockState(),
                BlockPredicate.matchesBlocks(
                        new BlockPos(0, -1, 0),
                        ModBlocks.SHALE_GRASS_BLOCK.get(),
                        Blocks.SANDSTONE,
                        ModBlocks.SHALE_BLOCK.get(),
                        ModBlocks.LIMESTONE_GRASS_BLOCK.get()
                )
        );

        context.register(LIMESTONE_BOULDER, new ConfiguredFeature<>(Feature.BLOCK_BLOB, config));
    }
}
