package com.acethewildfire.acesbs.util;

import com.acethewildfire.acesbs.AcesBS;
import com.acethewildfire.acesbs.item.AshenSteelItems;
import com.acethewildfire.acesbs.item.FractalDiamondItems;
import com.acethewildfire.acesbs.item.ModItems;
import com.acethewildfire.acesbs.item.PrismaSteelItems;
import net.fabricmc.fabric.api.loot.v3.LootTableEvents;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.Enchantments;
import net.minecraft.item.Item;
import net.minecraft.item.ItemConvertible;
import net.minecraft.item.Items;
import net.minecraft.loot.LootPool;
import net.minecraft.loot.LootTable;
import net.minecraft.loot.LootTables;
import net.minecraft.loot.condition.InvertedLootCondition;
import net.minecraft.loot.condition.LootCondition;
import net.minecraft.loot.condition.MatchToolLootCondition;
import net.minecraft.loot.condition.RandomChanceLootCondition;
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.component.ComponentPredicateTypes;
import net.minecraft.predicate.component.ComponentsPredicate;
import net.minecraft.predicate.item.EnchantmentPredicate;
import net.minecraft.predicate.item.EnchantmentsPredicate;
import net.minecraft.predicate.item.ItemPredicate;
import net.minecraft.registry.*;
import net.minecraft.util.Identifier;

import java.util.List;

public class ModLootTableModifier {
    public static LootCondition.Builder specialToolCondition(RegistryEntryLookup<Item> lookup, ItemConvertible... tools) {
        return MatchToolLootCondition.builder(
                ItemPredicate.Builder.create()
                        .items(lookup, tools)
        );
    }

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

        LootTableEvents.MODIFY.register((key, tableBuilder, source, wrapperLookup) -> {
            RegistryWrapper.Impl<Enchantment> impl = wrapperLookup.getOrThrow(RegistryKeys.ENCHANTMENT);
            RegistryEntryLookup<Item> itemLookup = wrapperLookup.getOrThrow(RegistryKeys.ITEM);

            Identifier id = key.getValue();

            // Only block loot tables
            if (!id.getPath().startsWith("blocks/")) return;

            String blockName = id.getPath().substring("blocks/".length());

            // Reliable ore detection
            if (!(blockName.endsWith("_ore") || blockName.contains("_ore_"))) return;

            AcesBS.LOGGER.info("Adding Prisma Pool to {}", blockName);

            LootCondition.Builder silkTouchCondition = MatchToolLootCondition.builder(
                    ItemPredicate.Builder.create().components(
                                    ComponentsPredicate.Builder.create()
                                            .partial(
                                                    ComponentPredicateTypes.ENCHANTMENTS,
                                                    EnchantmentsPredicate.enchantments(
                                                            List.of(new EnchantmentPredicate(impl.getOrThrow(Enchantments.SILK_TOUCH), NumberRange.IntRange.atLeast(1)))))
                                            .build()
                    )
                );

            LootPool.Builder extraPool = LootPool.builder()
                    .rolls(UniformLootNumberProvider.create(1, 2))
                    .conditionally(InvertedLootCondition.builder(silkTouchCondition))
                    .conditionally(specialToolCondition(itemLookup, PrismaSteelItems.PRISMA_STEEL_PICKAXE, PrismaSteelItems.PRISMA_STEEL_HAMMER, FractalDiamondItems.FRACTAL_DIAMOND_PICKAXE, FractalDiamondItems.FRACTAL_DIAMOND_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);
        });
    }

    public static void updateChests(){
        Identifier NETHER_FORTRESS_CHEST =
               Identifier.of("minecraft", "chests/nether_bridge");

            LootTableEvents.MODIFY.register((key, tableBuilder, source, wrapperLookup) -> {
                if (NETHER_FORTRESS_CHEST.equals(key.getValue())) {

                    LootPool.Builder pool = LootPool.builder()
                            .with(ItemEntry.builder(AshenSteelItems.ASHEN_SMITHING_TEMPLATE))
                            .conditionally(RandomChanceLootCondition.builder(0.1f));

                    tableBuilder.pool(pool);
                }
            });

        LootTableEvents.MODIFY.register((key, tableBuilder, source, wrapperLookup) -> {
            if (key.equals(LootTables.HERO_OF_THE_VILLAGE_ARMORER_GIFT_GAMEPLAY)) {

                LootPool.Builder pool = LootPool.builder()
                        .with(ItemEntry.builder(PrismaSteelItems.PRISMA_SMITHING_TEMPLATE))
                        .conditionally(RandomChanceLootCondition.builder(0.1f));

                tableBuilder.pool(pool);
            }
        });
    }

    public static void updateAll(){
        updateVanilla();
        updateChests();
    }
}
