package org.cyclops.everlastingabilities.recipe;

import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.EnumRarity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.util.NonNullList;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.registries.IForgeRegistryEntry;
import org.cyclops.everlastingabilities.ability.AbilityHelpers;
import org.cyclops.everlastingabilities.item.ItemAbilityTotem;
import org.cyclops.everlastingabilities.item.ItemAbilityTotemConfig;

import java.util.Random;

public class TotemRecycleRecipe extends IForgeRegistryEntry.Impl<IRecipe> implements IRecipe {

    private final Random rand = new Random();
    private long seed = rand.nextLong();
    
    @Override
    public boolean matches(InventoryCrafting invCrafting, World world) {
    
        int inputCount = 0;
        for (int i = 0; i < invCrafting.getSizeInventory(); i++) {
            ItemStack slot = invCrafting.getStackInSlot(i);
            if (!slot.isEmpty()) {
                if (slot.getItem() instanceof ItemAbilityTotem) {
                    inputCount++;
                }
                else {
                    // non-totem item found in recipe
                    return false;
                }
            }
        }
        return inputCount == ItemAbilityTotemConfig.totemCraftingCount;
    }
    
    @Override
    public ItemStack getCraftingResult(InventoryCrafting invCrafting) {
        // Item is being taken out of crafting grid.

        // Select one of the inputs at random, and use its rarity for the rarity of the output.
        int inputIndex = 0;
        rand.setSeed(seed);
        int inputTargetIndex = rand.nextInt(ItemAbilityTotemConfig.totemCraftingCount);
        EnumRarity rarity = EnumRarity.COMMON;

        for (int i = 0; i < invCrafting.getSizeInventory(); i++) {
            ItemStack slot = invCrafting.getStackInSlot(i);
            if (!slot.isEmpty()) {
                if (slot.getItem() instanceof ItemAbilityTotem) {
                    if (inputIndex >= inputTargetIndex) {
                        rarity = ItemAbilityTotem.getInstance().getRarity(slot);
                        break;
                    }
                    inputIndex++;
                }
                else {
                    // non-totem item found in recipe
                    // this should never happen because matches() will return false.
                    // We should probably throw() here.
                    return ItemStack.EMPTY;
                }
            }
        }

        // 20% chance of a bump
        if (rarity.ordinal() < EnumRarity.EPIC.ordinal() && rand.nextInt(100) < ItemAbilityTotemConfig.totemCraftingRarityIncreasePercent) {
            rarity = EnumRarity.values()[rarity.ordinal()+1];
        }

        return AbilityHelpers.getRandomTotem(rarity, rand);
    }

    @Override
    public boolean canFit(int width, int height) {
        return width * height >= ItemAbilityTotemConfig.totemCraftingCount;
    }

    @Override
    public ItemStack getRecipeOutput() {
        return new ItemStack(ItemAbilityTotem.getInstance());
    }
    
    @Override
    public NonNullList<ItemStack> getRemainingItems(InventoryCrafting inv) {
        seed++;
        return ForgeHooks.defaultRecipeGetRemainingItems(inv);
    }
}


@@ -388,16 +388,72 @@
 yEntry;%0A
+import org.cyclops.cyclopscore.helper.ItemStackHelpers;%0A
 import o
@@ -641,16 +641,75 @@
 onfig;%0A%0A
+import java.util.Collections;%0Aimport java.util.Comparator;%0A
 import j
@@ -1978,16 +1978,202 @@
 OMMON;%0A%0A
+        // Sort our input stacks, so we can deterministically select one specific one to determine the output rarity.%0A        NonNullList%3CItemStack%3E sortedStacks = NonNullList.create();%0A
         
@@ -2416,247 +2416,74 @@
     
-if (inputIndex %3E= inputTargetIndex) %7B%0A                        rarity = ItemAbilityTotem.getInstance().getRarity(slot);%0A                        break;%0A                    %7D%0A                    inputIndex++;%0A                %7D%0A               
+sortedStacks.add(invCrafting.getStackInSlot(i));%0A                %7D
  els
@@ -2767,25 +2767,24 @@
       %7D%0A
-%0A
         
 // 20%25 c
@@ -2779,92 +2779,430 @@
     
-// 20%25 chance of a bump%0A        if (rarity.ordinal() %3C EnumRarity.EPIC.ordinal() && 
+Collections.sort(sortedStacks, Comparator.comparingInt(ItemStackHelpers::getItemStackHashCode));%0A%0A        if (inputTargetIndex %3E= sortedStacks.size()) %7B%0A            // Should not be able to happen, unless some mod is doing funky stuff.%0A            return ItemStack.EMPTY;%0A        %7D%0A        rarity = ItemAbilityTotem.getInstance().getRarity(sortedStacks.get(inputTargetIndex));%0A%0A        // 20%25 chance of a bump%0A        if (
 rand
@@ -3274,16 +3274,64 @@
 ePercent
+ && rarity.ordinal() %3C EnumRarity.EPIC.ordinal()
 ) %7B%0A    

Make totem recycling more deterministic for different input orders