package com.acethewildfire.acesbs.util;

import com.acethewildfire.acesbs.AcesBS;
import com.acethewildfire.acesbs.item.ModItems;
import com.acethewildfire.acesbs.item.PrismaSteelItems;
import net.fabricmc.fabric.api.loot.v3.LootTableEvents;
import net.minecraft.block.Blocks;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.Enchantments;
import net.minecraft.item.ItemConvertible;
import net.minecraft.item.Items;
import net.minecraft.loot.LootPool;
import net.minecraft.loot.LootTable;
import net.minecraft.loot.condition.InvertedLootCondition;
import net.minecraft.loot.condition.LootCondition;
import net.minecraft.loot.condition.MatchToolLootCondition;
import net.minecraft.loot.entry.ItemEntry;
import net.minecraft.loot.function.ApplyBonusLootFunction;
import net.minecraft.loot.function.ExplosionDecayLootFunction;
import net.minecraft.loot.provider.number.UniformLootNumberProvider;
import net.minecraft.predicate.NumberRange;
import net.minecraft.predicate.item.EnchantmentPredicate;
import net.minecraft.predicate.item.EnchantmentsPredicate;
import net.minecraft.predicate.item.ItemPredicate;
import net.minecraft.predicate.item.ItemSubPredicateTypes;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.RegistryWrapper;

import java.util.ArrayList;
import java.util.List;

public class UpdateRecipies {
    private static LootCondition.Builder specialToolCondition(ItemConvertible... tools){
        return MatchToolLootCondition.builder(
                ItemPredicate.Builder.create()
                        .items(tools)
        );
    }

    public static void updateVanilla(){
        AcesBS.LOGGER.info("Updating vanilla Ore Drops for Prisma Steel");

        RegistryKey<LootTable> coalOreLootId = Blocks.COAL_ORE.getLootTableKey();
        RegistryKey<LootTable> copperOreLootId = Blocks.COPPER_ORE.getLootTableKey();
        RegistryKey<LootTable> ironOreLootId = Blocks.IRON_ORE.getLootTableKey();
        RegistryKey<LootTable> goldOreLootId = Blocks.GOLD_ORE.getLootTableKey();
        RegistryKey<LootTable> lapisOreLootId = Blocks.LAPIS_ORE.getLootTableKey();
        RegistryKey<LootTable> redstoneOreLootId = Blocks.REDSTONE_ORE.getLootTableKey();
        RegistryKey<LootTable> diamondOreLootId = Blocks.DIAMOND_ORE.getLootTableKey();
        RegistryKey<LootTable> emeraldOreLootId = Blocks.EMERALD_ORE.getLootTableKey();

        RegistryKey<LootTable> coalDeepslateOreLootId = Blocks.DEEPSLATE_COAL_ORE.getLootTableKey();
        RegistryKey<LootTable> copperDeepslateOreLootId = Blocks.DEEPSLATE_COPPER_ORE.getLootTableKey();
        RegistryKey<LootTable> ironDeepslateOreLootId = Blocks.DEEPSLATE_IRON_ORE.getLootTableKey();
        RegistryKey<LootTable> goldDeepslateOreLootId = Blocks.DEEPSLATE_GOLD_ORE.getLootTableKey();
        RegistryKey<LootTable> lapisDeepslateOreLootId = Blocks.DEEPSLATE_LAPIS_ORE.getLootTableKey();
        RegistryKey<LootTable> redstoneDeepslateOreLootId = Blocks.DEEPSLATE_REDSTONE_ORE.getLootTableKey();
        RegistryKey<LootTable> diamondDeepslateOreLootId = Blocks.DEEPSLATE_DIAMOND_ORE.getLootTableKey();
        RegistryKey<LootTable> emeraldDeepslateOreLootId = Blocks.DEEPSLATE_EMERALD_ORE.getLootTableKey();

        List<RegistryKey<LootTable>> ores = new ArrayList<>();

        ores.add(coalOreLootId);
        ores.add(copperOreLootId);
        ores.add(ironOreLootId);
        ores.add(goldOreLootId);
        ores.add(lapisOreLootId);
        ores.add(redstoneOreLootId);
        ores.add(diamondOreLootId);
        ores.add(emeraldOreLootId);

        ores.add(coalDeepslateOreLootId);
        ores.add(copperDeepslateOreLootId);
        ores.add(ironDeepslateOreLootId);
        ores.add(goldDeepslateOreLootId);
        ores.add(lapisDeepslateOreLootId);
        ores.add(redstoneDeepslateOreLootId);
        ores.add(diamondDeepslateOreLootId);
        ores.add(emeraldDeepslateOreLootId);




        LootTableEvents.MODIFY.register((key, tableBuilder, source, wrapperLookup) -> {
            RegistryWrapper.Impl<Enchantment> impl = wrapperLookup.getWrapperOrThrow(RegistryKeys.ENCHANTMENT);
            LootCondition.Builder silkTouchCondition = MatchToolLootCondition.builder(
                    ItemPredicate.Builder.create()
                            .subPredicate(
                                    ItemSubPredicateTypes.ENCHANTMENTS,
                                    EnchantmentsPredicate.enchantments(List.of(new EnchantmentPredicate(impl.getOrThrow(Enchantments.SILK_TOUCH), NumberRange.IntRange.atLeast(1))))
                )
            );

            if (source.isBuiltin() && ores.contains(key)) {
                LootPool.Builder extraPool = LootPool.builder()
                        .rolls(UniformLootNumberProvider.create(1, 2))
                        .conditionally(InvertedLootCondition.builder(silkTouchCondition))
                        .conditionally(specialToolCondition(PrismaSteelItems.PRISMA_STEEL_PICKAXE, PrismaSteelItems.PRISMA_STEEL_HAMMER))
                        .with(ItemEntry.builder(Items.AIR).weight(460))
                        .with(ItemEntry.builder(Items.COAL).weight(12))
                        .with(ItemEntry.builder(Items.RAW_COPPER).weight(10))
                        .with(ItemEntry.builder(Items.RAW_IRON).weight(6))
                        .with(ItemEntry.builder(Items.RAW_GOLD).weight(4))
                        .with(ItemEntry.builder(Items.LAPIS_LAZULI).weight(3))
                        .with(ItemEntry.builder(Items.REDSTONE).weight(2))
                        .with(ItemEntry.builder(ModItems.RAW_ENTROPY).weight(1))
                        .with(ItemEntry.builder(Items.DIAMOND).weight(1))
                        .with(ItemEntry.builder(Items.EMERALD).weight(1))
                        .apply(ApplyBonusLootFunction.oreDrops(impl.getOrThrow(Enchantments.FORTUNE)))
                        .apply(ExplosionDecayLootFunction.builder());

                // Add our extra drop pool to loot table
                tableBuilder.pool(extraPool);
            }
        });
    }
}
