package com.acethewildfire.acesbs.world;

import com.acethewildfire.acesbs.AcesBS;
import com.acethewildfire.acesbs.block.ModBlocks;
import net.minecraft.block.Blocks;
import net.minecraft.registry.Registerable;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.tag.BlockTags;
import net.minecraft.structure.rule.BlockMatchRuleTest;
import net.minecraft.structure.rule.RuleTest;
import net.minecraft.structure.rule.TagMatchRuleTest;
import net.minecraft.util.Identifier;
import net.minecraft.util.collection.DataPool;
import net.minecraft.util.math.intprovider.ConstantIntProvider;
import net.minecraft.util.math.intprovider.IntProvider;
import net.minecraft.util.math.intprovider.UniformIntProvider;
import net.minecraft.util.math.intprovider.WeightedListIntProvider;
import net.minecraft.world.gen.feature.*;
import net.minecraft.world.gen.feature.size.TwoLayersFeatureSize;
import net.minecraft.world.gen.foliage.CherryFoliagePlacer;
import net.minecraft.world.gen.stateprovider.BlockStateProvider;
import net.minecraft.world.gen.trunk.CherryTrunkPlacer;

import java.util.List;

public class ModConfiguredFeatures {
    // CF -> PF -> WG
    // CF: Could be a house
    // PF: How is it placed
    // WG: Where it is placed

    public static final RegistryKey<ConfiguredFeature<?, ?>> ENTROPY_ORE_KEY = registerKey("entropy_ore");
    public static final RegistryKey<ConfiguredFeature<?, ?>> DEEPSLATE_ENTROPY_ORE_KEY = registerKey("deepslate_entropy_ore");
    public static final RegistryKey<ConfiguredFeature<?, ?>> INFERNAL_ASHES_ORE_KEY = registerKey("infernal_ashes_ore");
    public static final RegistryKey<ConfiguredFeature<?, ?>> ENDTROPY_ORE_KEY = registerKey("endtropy_ore");

    public static final RegistryKey<ConfiguredFeature<?, ?>> LEMONWOOD_KEY = registerKey("lemonwood");

    public static void bootstrap(Registerable<ConfiguredFeature<?, ?>> context) {
        RuleTest stoneReplaceables = new TagMatchRuleTest(BlockTags.STONE_ORE_REPLACEABLES);
        RuleTest deepslateReplaceables = new TagMatchRuleTest(BlockTags.DEEPSLATE_ORE_REPLACEABLES);
        RuleTest netherReplaceables = new TagMatchRuleTest(BlockTags.BASE_STONE_NETHER);
        RuleTest endReplaceables = new BlockMatchRuleTest(Blocks.END_STONE);

        List<OreFeatureConfig.Target> overworldEntropyOres =
                List.of(OreFeatureConfig.createTarget(stoneReplaceables, ModBlocks.ENTROPY_ORE.getDefaultState()));

        List<OreFeatureConfig.Target> overworldDeepslateEntropyOres =
                List.of(OreFeatureConfig.createTarget(deepslateReplaceables, ModBlocks.DEEPSLATE_ENTROPY_ORE.getDefaultState()));

        List<OreFeatureConfig.Target> netherAshesOres =
                List.of(OreFeatureConfig.createTarget(netherReplaceables, ModBlocks.INFERNAL_ASHES_ORE.getDefaultState()));

        List<OreFeatureConfig.Target> endEndtropyOres =
                List.of(OreFeatureConfig.createTarget(endReplaceables, ModBlocks.ENDTROPY_ORE.getDefaultState()));


        register(context, ENTROPY_ORE_KEY, Feature.ORE, new OreFeatureConfig(overworldEntropyOres, 4, 0.0F));
        register(context, DEEPSLATE_ENTROPY_ORE_KEY, Feature.ORE, new OreFeatureConfig(overworldDeepslateEntropyOres, 4, 0.0F));
        register(context, INFERNAL_ASHES_ORE_KEY, Feature.ORE, new OreFeatureConfig(netherAshesOres, 4, 0.0F));
        register(context, ENDTROPY_ORE_KEY, Feature.ORE, new OreFeatureConfig(endEndtropyOres, 4, 0.0F));


        register(context, LEMONWOOD_KEY, Feature.TREE, new TreeFeatureConfig.Builder(
                BlockStateProvider.of(ModBlocks.LEMONWOOD_LOG),
                new CherryTrunkPlacer(7, 1, 0, new WeightedListIntProvider(new DataPool.Builder<IntProvider>().add(ConstantIntProvider.create(1), 1).add(ConstantIntProvider.create(2), 1).add(ConstantIntProvider.create(3), 1).build()), UniformIntProvider.create(2, 4), UniformIntProvider.create(-4, -3), UniformIntProvider.create(-1, 0)),

                BlockStateProvider.of(ModBlocks.LEMONWOOD_LEAVES),
                new CherryFoliagePlacer(ConstantIntProvider.create(4), ConstantIntProvider.create(0), ConstantIntProvider.create(5), 0.25F, 0.5F, 0.16666667F, 0.33333334F),

                new TwoLayersFeatureSize(1, 0, 2)).build()
        );
    }

    public static RegistryKey<ConfiguredFeature<?, ?>> registerKey(String name) {
        return RegistryKey.of(RegistryKeys.CONFIGURED_FEATURE, Identifier.of(AcesBS.MOD_ID, name));
    }

    private static <FC extends FeatureConfig, F extends Feature<FC>> void register(Registerable<ConfiguredFeature<?, ?>> context,
                                                                                   RegistryKey<ConfiguredFeature<?, ?>> key, F feature, FC configuration) {
        context.register(key, new ConfiguredFeature<>(feature, configuration));
    }

}
