package com.acethewildfire.acesbs.datagen;

import com.acethewildfire.acesbs.AcesBS;
import com.acethewildfire.acesbs.block.ModBlocks;
import com.acethewildfire.acesbs.item.ModItems;
import com.acethewildfire.acesbs.item.PrismaSteelItems;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
import net.minecraft.block.Blocks;
import net.minecraft.data.server.recipe.RecipeExporter;
import net.minecraft.data.server.recipe.ShapedRecipeJsonBuilder;
import net.minecraft.data.server.recipe.ShapelessRecipeJsonBuilder;
import net.minecraft.item.ItemConvertible;
import net.minecraft.item.Items;
import net.minecraft.recipe.*;
import net.minecraft.recipe.book.RecipeCategory;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.util.Identifier;

import java.util.concurrent.CompletableFuture;

public class ModRecipeProvider extends FabricRecipeProvider {
    public ModRecipeProvider(FabricDataOutput output, CompletableFuture<RegistryWrapper.WrapperLookup> registriesFuture) {
        super(output, registriesFuture);
    }

    @Override
    public void generate(RecipeExporter recipeExporter) {

//        List<ItemConvertible> ENTROPY_SMELTABLES = List.of(ModItems.RAW_ENTROPY, ModBlocks.ENTROPY_ORE, ModBlocks.DEEPSLATE_ENTROPY_ORE);
//        List<ItemConvertible> ENDTROPY_SMELTABLES = List.of(ModItems.RAW_ENDTROPY, ModBlocks.ENDTROPY_ORE);
//
//        offerBlasting(recipeExporter, ENTROPY_SMELTABLES, RecipeCategory.MISC, ModItems.STABLE_ENTROPY, 0.5f, 2000, "stable_entropy");
//        offerBlasting(recipeExporter, ENDTROPY_SMELTABLES, RecipeCategory.MISC, ModItems.STABLE_ENDTROPY, 0.5f, 2000, "stable_endtropy");

        offerReversibleCompactingRecipes(recipeExporter, RecipeCategory.BUILDING_BLOCKS, ModItems.RAW_ENTROPY, RecipeCategory.DECORATIONS, ModBlocks.ENTROPY_BLOCK);
        offerReversibleCompactingRecipes(recipeExporter, RecipeCategory.BUILDING_BLOCKS, ModItems.STABLE_ENTROPY, RecipeCategory.DECORATIONS, ModBlocks.STABLE_ENTROPY_BLOCK);
        // ENDTROPY BLOCKS
        //        offerReversibleCompactingRecipes(recipeExporter, RecipeCategory.BUILDING_BLOCKS, ModItems.RAW_ENTROPY, RecipeCategory.DECORATIONS, ModBlocks.ENDTROPY_BLOCK);
        //        offerReversibleCompactingRecipes(recipeExporter, RecipeCategory.BUILDING_BLOCKS, ModItems.STABLE_ENTROPY, RecipeCategory.DECORATIONS, ModBlocks.STABLE_ENDTROPY_BLOCK);
        offerReversibleCompactingRecipes(recipeExporter, RecipeCategory.BUILDING_BLOCKS, PrismaSteelItems.PRISMA_STEEL, RecipeCategory.DECORATIONS, ModBlocks.PRISMA_STEEL_BLOCK);
        offerReversibleCompactingRecipes(recipeExporter, RecipeCategory.BUILDING_BLOCKS, ModItems.INFERNAL_ASHES, RecipeCategory.DECORATIONS, ModBlocks.INFERNAL_ASHES_BLOCK);


        offerAllFoodCookingRecipes(recipeExporter, 200, ModItems.LEMON, ModItems.COOKED_LEMON, 0.35F);

        ShapedRecipeJsonBuilder.create(RecipeCategory.COMBAT, ModItems.ORACLE_LEMON, 4)
                .pattern("###")
                .pattern("#L#")
                .pattern("###")
                .input('#', ModItems.STABLE_ENTROPY)
                .input('L', ModItems.LEMON)
                .criterion(hasItem(ModItems.LEMON), conditionsFromItem(ModItems.LEMON))
                .offerTo(recipeExporter);

        ShapelessRecipeJsonBuilder.create(RecipeCategory.FOOD, ModItems.BRICKED_UP, 1)
                .input(Items.BRICK, 1)
                .input(ModItems.STABLE_ENDTROPY, 1)
                .criterion(hasItem(ModItems.STABLE_ENDTROPY), conditionsFromItem(ModItems.STABLE_ENDTROPY))
                .offerTo(recipeExporter);

        ShapedRecipeJsonBuilder.create(RecipeCategory.DECORATIONS, ModBlocks.CRYSTAL_ENTROPY, 8)
                .pattern("###")
                .pattern("#S#")
                .pattern("###")
                .input('#', Blocks.GLASS)
                .input('S', ModItems.STABLE_ENTROPY)
                .criterion(hasItem(ModItems.STABLE_ENTROPY), conditionsFromItem(ModItems.STABLE_ENTROPY))
                .offerTo(recipeExporter, Identifier.of(AcesBS.MOD_ID, "crystal_entropy_from_stable_and_glass"));

        ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, ModBlocks.ENTROPIC_STABILIZER, 1)
                .pattern("IRI")
                .pattern("IBI")
                .pattern("III")
                .input('I', Items.IRON_INGOT)
                .input('R', ModItems.RAW_ENTROPY)
                .input('B', Blocks.BLUE_ICE)
                .criterion(hasItem(ModItems.RAW_ENTROPY), conditionsFromItem(ModItems.RAW_ENTROPY))
                .offerTo(recipeExporter);

        ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, ModBlocks.ENTROPIC_EVISCERATOR, 1)
                .pattern("III")
                .pattern("SES")
                .pattern("III")
                .input('I', Items.IRON_INGOT)
                .input('S', Blocks.STONECUTTER)
                .input('E', ModItems.STABLE_ENTROPY)
                .criterion(hasItem(Blocks.STONECUTTER), conditionsFromItem(Blocks.STONECUTTER))
                .offerTo(recipeExporter);

        ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, ModBlocks.ENTROPIC_ENTANGLER, 1)
                .pattern("ISI")
                .pattern("BGB")
                .pattern("ISI")
                .input('I', Items.IRON_INGOT)
                .input('S', ModItems.STABLE_ENTROPY)
                .input('B', Items.BUCKET)
                .input('G', Blocks.GOLD_BLOCK)
                .criterion(hasItem(ModItems.RAW_ENTROPY), conditionsFromItem(ModItems.RAW_ENTROPY))
                .offerTo(recipeExporter);

        ShapedRecipeJsonBuilder.create(RecipeCategory.DECORATIONS, ModBlocks.CRYSTAL_ENTROPY_PANE, 16)
                .pattern("###")
                .pattern("###")
                .input('#', ModBlocks.CRYSTAL_ENTROPY)
                .criterion(hasItem(ModBlocks.CRYSTAL_ENTROPY), conditionsFromItem(ModBlocks.CRYSTAL_ENTROPY))
                .offerTo(recipeExporter);

        ShapelessRecipeJsonBuilder.create(RecipeCategory.BUILDING_BLOCKS, ModBlocks.LIZARD_PLANKS, 4)
                .input(Blocks.BIRCH_PLANKS, 4)
                .input(ModItems.RAW_ENTROPY, 1)
                .input(Items.GREEN_DYE, 1)
                .criterion(hasItem(Items.GREEN_DYE), conditionsFromItem(Items.GREEN_DYE))
                .offerTo(recipeExporter);

        ShapelessRecipeJsonBuilder.create(RecipeCategory.REDSTONE, ModBlocks.LIZARD_BUTTON, 1)
                .input(ModBlocks.LIZARD_PLANKS, 1)
                .criterion(hasItem(ModBlocks.LIZARD_PLANKS), conditionsFromItem(ModBlocks.LIZARD_PLANKS))
                .offerTo(recipeExporter);

        ShapelessRecipeJsonBuilder.create(RecipeCategory.DECORATIONS, ModBlocks.LEMONWOOD_SAPLING, 1)
                .input(Blocks.BIRCH_SAPLING, 1)
                .input(ModItems.LEMON, 1)
                .criterion(hasItem(ModItems.LEMON), conditionsFromItem(ModItems.LEMON))
                .offerTo(recipeExporter);

        ShapelessRecipeJsonBuilder.create(RecipeCategory.BUILDING_BLOCKS, ModBlocks.LEMONWOOD_PLANKS, 4)
                .input(ModBlocks.LEMONWOOD_LOG, 1)
                .criterion(hasItem(ModBlocks.LEMONWOOD_LOG), conditionsFromItem(ModBlocks.LEMONWOOD_LOG))
                .offerTo(recipeExporter, Identifier.of(AcesBS.MOD_ID, "lemonwood_planks_from_lemonwood_log"));

        ShapelessRecipeJsonBuilder.create(RecipeCategory.BUILDING_BLOCKS, ModBlocks.LEMONWOOD_PLANKS, 4)
                .input(ModBlocks.STRIPPED_LEMONWOOD_LOG, 1)
                .criterion(hasItem(ModBlocks.STRIPPED_LEMONWOOD_LOG), conditionsFromItem(ModBlocks.STRIPPED_LEMONWOOD_LOG))
                .offerTo(recipeExporter, Identifier.of(AcesBS.MOD_ID, "lemonwood_planks_from_stripped_lemonwood_log"));

        ShapelessRecipeJsonBuilder.create(RecipeCategory.BUILDING_BLOCKS, ModBlocks.LEMONWOOD_PLANKS, 4)
                .input(ModBlocks.LEMONWOOD_WOOD, 1)
                .criterion(hasItem(ModBlocks.LEMONWOOD_WOOD), conditionsFromItem(ModBlocks.LEMONWOOD_WOOD))
                .offerTo(recipeExporter, Identifier.of(AcesBS.MOD_ID, "lemonwood_planks_from_lemonwood_wood"));

        ShapelessRecipeJsonBuilder.create(RecipeCategory.BUILDING_BLOCKS, ModBlocks.LEMONWOOD_PLANKS, 4)
                .input(ModBlocks.STRIPPED_LEMONWOOD_WOOD, 1)
                .criterion(hasItem(ModBlocks.STRIPPED_LEMONWOOD_WOOD), conditionsFromItem(ModBlocks.STRIPPED_LEMONWOOD_WOOD))
                .offerTo(recipeExporter, Identifier.of(AcesBS.MOD_ID, "lemonwood_planks_from_stripped_lemonwood_wood"));

        ShapedRecipeJsonBuilder.create(RecipeCategory.BUILDING_BLOCKS, ModBlocks.LEMONWOOD_WOOD, 3)
                .pattern("## ")
                .pattern("## ")
                .pattern("   ")
                .input('#', ModBlocks.LEMONWOOD_LOG)
                .criterion(hasItem(ModBlocks.LEMONWOOD_LOG), conditionsFromItem(ModBlocks.LEMONWOOD_LOG))
                .offerTo(recipeExporter);

        ShapedRecipeJsonBuilder.create(RecipeCategory.BUILDING_BLOCKS, ModBlocks.STRIPPED_LEMONWOOD_WOOD, 3)
                .pattern("## ")
                .pattern("## ")
                .pattern("   ")
                .input('#', ModBlocks.STRIPPED_LEMONWOOD_LOG)
                .criterion(hasItem(ModBlocks.STRIPPED_LEMONWOOD_LOG), conditionsFromItem(ModBlocks.STRIPPED_LEMONWOOD_LOG))
                .offerTo(recipeExporter);

        createStairsRecipe(ModBlocks.LEMONWOOD_STAIRS, Ingredient.ofItems(ModBlocks.LEMONWOOD_PLANKS))
                .criterion(hasItem(ModBlocks.LEMONWOOD_PLANKS), conditionsFromItem(ModBlocks.LEMONWOOD_PLANKS))
                .offerTo(recipeExporter);
        createSlabRecipe(RecipeCategory.BUILDING_BLOCKS, ModBlocks.LEMONWOOD_SLAB, Ingredient.ofItems(ModBlocks.LEMONWOOD_PLANKS))
                .criterion(hasItem(ModBlocks.LEMONWOOD_PLANKS), conditionsFromItem(ModBlocks.LEMONWOOD_PLANKS))
                .offerTo(recipeExporter);

        ShapelessRecipeJsonBuilder.create(RecipeCategory.REDSTONE, ModBlocks.LEMONWOOD_BUTTON, 1)
                .input(ModBlocks.LEMONWOOD_PLANKS, 1)
                .criterion(hasItem(ModBlocks.LEMONWOOD_PLANKS), conditionsFromItem(ModBlocks.LEMONWOOD_PLANKS))
                .offerTo(recipeExporter);
        createPressurePlateRecipe(RecipeCategory.REDSTONE, ModBlocks.LEMONWOOD_PRESSURE_PLATE, Ingredient.ofItems(ModBlocks.LEMONWOOD_PLANKS))
                .criterion(hasItem(ModBlocks.LEMONWOOD_PLANKS), conditionsFromItem(ModBlocks.LEMONWOOD_PLANKS))
                .offerTo(recipeExporter);

        createFenceRecipe(ModBlocks.LEMONWOOD_FENCE, Ingredient.ofItems(ModBlocks.LEMONWOOD_PLANKS))
                .criterion(hasItem(ModBlocks.LEMONWOOD_PLANKS), conditionsFromItem(ModBlocks.LEMONWOOD_PLANKS))
                .offerTo(recipeExporter);
        createFenceGateRecipe(ModBlocks.LEMONWOOD_FENCE_GATE, Ingredient.ofItems(ModBlocks.LEMONWOOD_PLANKS))
                .criterion(hasItem(ModBlocks.LEMONWOOD_PLANKS), conditionsFromItem(ModBlocks.LEMONWOOD_PLANKS))
                .offerTo(recipeExporter);
        offerWallRecipe(recipeExporter, RecipeCategory.BUILDING_BLOCKS, ModBlocks.LEMONWOOD_WALL, ModBlocks.LEMONWOOD_PLANKS);

        createDoorRecipe(ModBlocks.LEMONWOOD_DOOR, Ingredient.ofItems(ModBlocks.LEMONWOOD_PLANKS))
                .criterion(hasItem(ModBlocks.LEMONWOOD_PLANKS), conditionsFromItem(ModBlocks.LEMONWOOD_PLANKS))
                .offerTo(recipeExporter);
        createTrapdoorRecipe(ModBlocks.LEMONWOOD_TRAPDOOR, Ingredient.ofItems(ModBlocks.LEMONWOOD_PLANKS))
                .criterion(hasItem(ModBlocks.LEMONWOOD_PLANKS), conditionsFromItem(ModBlocks.LEMONWOOD_PLANKS))
                .offerTo(recipeExporter);

        SwordRecipeJsonBuilder(recipeExporter, PrismaSteelItems.PRISMA_STEEL_SWORD, PrismaSteelItems.PRISMA_STEEL, Items.STICK, PrismaSteelItems.PRISMA_STEEL);
        PickaxeRecipeJsonBuilder(recipeExporter, PrismaSteelItems.PRISMA_STEEL_PICKAXE, PrismaSteelItems.PRISMA_STEEL, Items.STICK, PrismaSteelItems.PRISMA_STEEL);
        HammerRecipeJsonBuilder(recipeExporter, PrismaSteelItems.PRISMA_STEEL_HAMMER, PrismaSteelItems.PRISMA_STEEL, ModBlocks.PRISMA_STEEL_BLOCK, Items.STICK, PrismaSteelItems.PRISMA_STEEL);
        AxeRecipeJsonBuilder(recipeExporter, PrismaSteelItems.PRISMA_STEEL_AXE, PrismaSteelItems.PRISMA_STEEL, Items.STICK, PrismaSteelItems.PRISMA_STEEL);
        ShovelRecipeJsonBuilder(recipeExporter, PrismaSteelItems.PRISMA_STEEL_SHOVEL, PrismaSteelItems.PRISMA_STEEL, Items.STICK, PrismaSteelItems.PRISMA_STEEL);
        HoeRecipeJsonBuilder(recipeExporter, PrismaSteelItems.PRISMA_STEEL_HOE, PrismaSteelItems.PRISMA_STEEL, Items.STICK, PrismaSteelItems.PRISMA_STEEL);

        offerSmithingTrimRecipe(recipeExporter, PrismaSteelItems.PRISMA_SMITHING_TEMPLATE, Identifier.of(AcesBS.MOD_ID, "prisma"));

        // For 2+ recipes with the same RESULT use
        // .offerTo(recipeExporter, Identifier.of(AcesBS.MOD_ID, "output_item_from_input_item"));
    }


    private void SwordRecipeJsonBuilder(RecipeExporter recipeExporter, ItemConvertible result, ItemConvertible headMaterial, ItemConvertible handleMaterial, ItemConvertible criterionItem){
        ShapedRecipeJsonBuilder.create(RecipeCategory.COMBAT, result)
                .pattern(" # ")
                .pattern(" # ")
                .pattern(" I ")
                .input('#', headMaterial)
                .input('I', handleMaterial)
                .criterion(hasItem(criterionItem), conditionsFromItem(criterionItem))
                .offerTo(recipeExporter);
    }
    private void PickaxeRecipeJsonBuilder(RecipeExporter recipeExporter, ItemConvertible result, ItemConvertible headMaterial, ItemConvertible handleMaterial, ItemConvertible criterionItem){
        ShapedRecipeJsonBuilder.create(RecipeCategory.TOOLS, result)
                .pattern("###")
                .pattern(" I ")
                .pattern(" I ")
                .input('#', headMaterial)
                .input('I', handleMaterial)
                .criterion(hasItem(criterionItem), conditionsFromItem(criterionItem))
                .offerTo(recipeExporter);
    }
    private void HammerRecipeJsonBuilder(RecipeExporter recipeExporter, ItemConvertible result, ItemConvertible headMaterial, ItemConvertible headMaterialBlock, ItemConvertible handleMaterial, ItemConvertible criterionItem){
        ShapedRecipeJsonBuilder.create(RecipeCategory.TOOLS, result)
                .pattern("B#B")
                .pattern(" I ")
                .pattern(" I ")
                .input('B', headMaterialBlock)
                .input('#', headMaterial)
                .input('I', handleMaterial)
                .criterion(hasItem(criterionItem), conditionsFromItem(criterionItem))
                .offerTo(recipeExporter);
    }
    private void AxeRecipeJsonBuilder(RecipeExporter recipeExporter, ItemConvertible result, ItemConvertible headMaterial, ItemConvertible handleMaterial, ItemConvertible criterionItem){
        ShapedRecipeJsonBuilder.create(RecipeCategory.TOOLS, result)
                .pattern("## ")
                .pattern("#I ")
                .pattern(" I ")
                .input('#', headMaterial)
                .input('I', handleMaterial)
                .criterion(hasItem(criterionItem), conditionsFromItem(criterionItem))
                .offerTo(recipeExporter, Identifier.of(AcesBS.MOD_ID, result.asItem().getName().getString() + ".left"));
        ShapedRecipeJsonBuilder.create(RecipeCategory.TOOLS, result)
                .pattern(" ##")
                .pattern(" I#")
                .pattern(" I ")
                .input('#', headMaterial)
                .input('I', handleMaterial)
                .criterion(hasItem(criterionItem), conditionsFromItem(criterionItem))
                .offerTo(recipeExporter, Identifier.of(AcesBS.MOD_ID, result.asItem().getName().getString() + ".right"));
    }
    private void ShovelRecipeJsonBuilder(RecipeExporter recipeExporter, ItemConvertible result, ItemConvertible headMaterial, ItemConvertible handleMaterial, ItemConvertible criterionItem){
        ShapedRecipeJsonBuilder.create(RecipeCategory.TOOLS, result)
                .pattern(" # ")
                .pattern(" I ")
                .pattern(" I ")
                .input('#', headMaterial)
                .input('I', handleMaterial)
                .criterion(hasItem(criterionItem), conditionsFromItem(criterionItem))
                .offerTo(recipeExporter);
    }
    private void HoeRecipeJsonBuilder(RecipeExporter recipeExporter, ItemConvertible result, ItemConvertible headMaterial, ItemConvertible handleMaterial, ItemConvertible criterionItem){
        ShapedRecipeJsonBuilder.create(RecipeCategory.TOOLS, result)
                .pattern("## ")
                .pattern(" I ")
                .pattern(" I ")
                .input('#', headMaterial)
                .input('I', handleMaterial)
                .criterion(hasItem(criterionItem), conditionsFromItem(criterionItem))
                .offerTo(recipeExporter, Identifier.of(AcesBS.MOD_ID, result.asItem().getName().getString() + ".left"));
        ShapedRecipeJsonBuilder.create(RecipeCategory.TOOLS, result)
                .pattern(" ##")
                .pattern(" I ")
                .pattern(" I ")
                .input('#', headMaterial)
                .input('I', handleMaterial)
                .criterion(hasItem(criterionItem), conditionsFromItem(criterionItem))
                .offerTo(recipeExporter, Identifier.of(AcesBS.MOD_ID, result.asItem().getName().getString() + ".right"));
    }


    public void offerAllFoodCookingRecipes (RecipeExporter recipeExporter, int baseCookingTime, ItemConvertible raw_item, ItemConvertible cooked_item, float experience ){
        offerFoodCookingRecipe(recipeExporter, "smoking", RecipeSerializer.SMOKING, SmokingRecipe::new,baseCookingTime/2, raw_item, cooked_item, experience);
        offerFoodCookingRecipe(recipeExporter, "campfire_cooking", RecipeSerializer.CAMPFIRE_COOKING, CampfireCookingRecipe::new, baseCookingTime*3, raw_item, cooked_item, experience);
        offerFoodCookingRecipe(recipeExporter, "smelting", RecipeSerializer.SMELTING, SmeltingRecipe::new, baseCookingTime, raw_item, cooked_item, experience);
    }
}
