package net.minecraft.world.inventory;

import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.ItemLike;
import java.util.function.Function;
import java.util.stream.Collectors;
import net.minecraft.world.item.Item;
import net.minecraft.core.BlockPos;
import java.util.Iterator;
import net.minecraft.world.item.enchantment.Enchantment;
import java.util.Map;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.level.Level;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.ExperienceOrb;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.Container;

public class GrindstoneMenu extends AbstractContainerMenu {
    private final Container resultSlots;
    private final Container repairSlots;
    private final ContainerLevelAccess access;
    
    public GrindstoneMenu(final int integer, final Inventory ayi) {
        this(integer, ayi, ContainerLevelAccess.NULL);
    }
    
    public GrindstoneMenu(final int integer, final Inventory ayi, final ContainerLevelAccess bax) {
        super(MenuType.GRINDSTONE, integer);
        this.resultSlots = new ResultContainer();
        this.repairSlots = new SimpleContainer(2) {
            @Override
            public void setChanged() {
                super.setChanged();
                GrindstoneMenu.this.slotsChanged(this);
            }
        };
        this.access = bax;
        this.addSlot(new Slot(this.repairSlots, 0, 49, 19) {
            @Override
            public boolean mayPlace(final ItemStack ben) {
                return ben.isDamageableItem() || ben.getItem() == Items.ENCHANTED_BOOK || ben.isEnchanted();
            }
        });
        this.addSlot(new Slot(this.repairSlots, 1, 49, 40) {
            @Override
            public boolean mayPlace(final ItemStack ben) {
                return ben.isDamageableItem() || ben.getItem() == Items.ENCHANTED_BOOK || ben.isEnchanted();
            }
        });
        this.addSlot(new Slot(this.resultSlots, 2, 129, 34) {
            @Override
            public boolean mayPlace(final ItemStack ben) {
                return false;
            }
            
            @Override
            public ItemStack onTake(final Player ayj, final ItemStack ben) {
                int integer4;
                int integer5;
                bax.execute((bjw, fk) -> {
                    integer4 = this.getExperienceAmount(bjw);
                    while (integer4 > 0) {
                        integer5 = ExperienceOrb.getExperienceValue(integer4);
                        integer4 -= integer5;
                        bjw.addFreshEntity(new ExperienceOrb(bjw, fk.getX(), fk.getY() + 0.5, fk.getZ() + 0.5, integer5));
                    }
                    bjw.levelEvent(1042, fk, 0);
                    return;
                });
                GrindstoneMenu.this.repairSlots.setItem(0, ItemStack.EMPTY);
                GrindstoneMenu.this.repairSlots.setItem(1, ItemStack.EMPTY);
                return ben;
            }
            
            private int getExperienceAmount(final Level bjw) {
                int integer3 = 0;
                integer3 += this.getExperienceFromItem(GrindstoneMenu.this.repairSlots.getItem(0));
                integer3 += this.getExperienceFromItem(GrindstoneMenu.this.repairSlots.getItem(1));
                if (integer3 > 0) {
                    final int integer4 = (int)Math.ceil(integer3 / 2.0);
                    return integer4 + bjw.random.nextInt(integer4);
                }
                return 0;
            }
            
            private int getExperienceFromItem(final ItemStack ben) {
                int integer3 = 0;
                final Map<Enchantment, Integer> map4 = EnchantmentHelper.getEnchantments(ben);
                for (final Map.Entry<Enchantment, Integer> entry6 : map4.entrySet()) {
                    final Enchantment bhx7 = entry6.getKey();
                    final Integer integer4 = entry6.getValue();
                    if (!bhx7.isCurse()) {
                        integer3 += bhx7.getMinCost(integer4);
                    }
                }
                return integer3;
            }
        });
        for (int integer2 = 0; integer2 < 3; ++integer2) {
            for (int integer3 = 0; integer3 < 9; ++integer3) {
                this.addSlot(new Slot(ayi, integer3 + integer2 * 9 + 9, 8 + integer3 * 18, 84 + integer2 * 18));
            }
        }
        for (int integer2 = 0; integer2 < 9; ++integer2) {
            this.addSlot(new Slot(ayi, integer2, 8 + integer2 * 18, 142));
        }
    }
    
    @Override
    public void slotsChanged(final Container aje) {
        super.slotsChanged(aje);
        if (aje == this.repairSlots) {
            this.createResult();
        }
    }
    
    private void createResult() {
        final ItemStack ben2 = this.repairSlots.getItem(0);
        final ItemStack ben3 = this.repairSlots.getItem(1);
        final boolean boolean4 = !ben2.isEmpty() || !ben3.isEmpty();
        final boolean boolean5 = !ben2.isEmpty() && !ben3.isEmpty();
        if (boolean4) {
            final boolean boolean6 = (!ben2.isEmpty() && ben2.getItem() != Items.ENCHANTED_BOOK && !ben2.isEnchanted()) || (!ben3.isEmpty() && ben3.getItem() != Items.ENCHANTED_BOOK && !ben3.isEnchanted());
            if (ben2.getCount() > 1 || ben3.getCount() > 1 || (!boolean5 && boolean6)) {
                this.resultSlots.setItem(0, ItemStack.EMPTY);
                this.broadcastChanges();
                return;
            }
            int integer8 = 1;
            int integer12;
            ItemStack ben4;
            if (boolean5) {
                if (ben2.getItem() != ben3.getItem()) {
                    this.resultSlots.setItem(0, ItemStack.EMPTY);
                    this.broadcastChanges();
                    return;
                }
                final Item bei10 = ben2.getItem();
                final int integer9 = bei10.getMaxDamage() - ben2.getDamageValue();
                final int integer10 = bei10.getMaxDamage() - ben3.getDamageValue();
                final int integer11 = integer9 + integer10 + bei10.getMaxDamage() * 5 / 100;
                integer12 = Math.max(bei10.getMaxDamage() - integer11, 0);
                ben4 = this.mergeEnchants(ben2, ben3);
                if (!ben4.isDamageableItem()) {
                    if (!ItemStack.matches(ben2, ben3)) {
                        this.resultSlots.setItem(0, ItemStack.EMPTY);
                        this.broadcastChanges();
                        return;
                    }
                    integer8 = 2;
                }
            }
            else {
                final boolean boolean7 = !ben2.isEmpty();
                integer12 = (boolean7 ? ben2.getDamageValue() : ben3.getDamageValue());
                ben4 = (boolean7 ? ben2 : ben3);
            }
            this.resultSlots.setItem(0, this.removeNonCurses(ben4, integer12, integer8));
        }
        else {
            this.resultSlots.setItem(0, ItemStack.EMPTY);
        }
        this.broadcastChanges();
    }
    
    private ItemStack mergeEnchants(final ItemStack ben1, final ItemStack ben2) {
        final ItemStack ben3 = ben1.copy();
        final Map<Enchantment, Integer> map5 = EnchantmentHelper.getEnchantments(ben2);
        for (final Map.Entry<Enchantment, Integer> entry7 : map5.entrySet()) {
            final Enchantment bhx8 = entry7.getKey();
            if (!bhx8.isCurse() || EnchantmentHelper.getItemEnchantmentLevel(bhx8, ben3) == 0) {
                ben3.enchant(bhx8, entry7.getValue());
            }
        }
        return ben3;
    }
    
    private ItemStack removeNonCurses(final ItemStack ben, final int integer2, final int integer3) {
        ItemStack ben2 = ben.copy();
        ben2.removeTagKey("Enchantments");
        ben2.removeTagKey("StoredEnchantments");
        if (integer2 > 0) {
            ben2.setDamageValue(integer2);
        }
        else {
            ben2.removeTagKey("Damage");
        }
        ben2.setCount(integer3);
        final Map<Enchantment, Integer> map6 = EnchantmentHelper.getEnchantments(ben).entrySet().stream().filter(entry -> entry.getKey().isCurse()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        EnchantmentHelper.setEnchantments(map6, ben2);
        ben2.setRepairCost(0);
        if (ben2.getItem() == Items.ENCHANTED_BOOK && map6.size() == 0) {
            ben2 = new ItemStack(Items.BOOK);
            if (ben.hasCustomHoverName()) {
                ben2.setHoverName(ben.getHoverName());
            }
        }
        for (int integer4 = 0; integer4 < map6.size(); ++integer4) {
            ben2.setRepairCost(AnvilMenu.calculateIncreasedRepairCost(ben2.getBaseRepairCost()));
        }
        return ben2;
    }
    
    @Override
    public void removed(final Player ayj) {
        super.removed(ayj);
        this.access.execute((bjw, fk) -> this.clearContainer(ayj, bjw, this.repairSlots));
    }
    
    @Override
    public boolean stillValid(final Player ayj) {
        return AbstractContainerMenu.stillValid(this.access, ayj, Blocks.GRINDSTONE);
    }
    
    @Override
    public ItemStack quickMoveStack(final Player ayj, final int integer) {
        ItemStack ben4 = ItemStack.EMPTY;
        final Slot bca5 = this.slots.get(integer);
        if (bca5 != null && bca5.hasItem()) {
            final ItemStack ben5 = bca5.getItem();
            ben4 = ben5.copy();
            final ItemStack ben6 = this.repairSlots.getItem(0);
            final ItemStack ben7 = this.repairSlots.getItem(1);
            if (integer == 2) {
                if (!this.moveItemStackTo(ben5, 3, 39, true)) {
                    return ItemStack.EMPTY;
                }
                bca5.onQuickCraft(ben5, ben4);
            }
            else if (integer == 0 || integer == 1) {
                if (!this.moveItemStackTo(ben5, 3, 39, false)) {
                    return ItemStack.EMPTY;
                }
            }
            else if (ben6.isEmpty() || ben7.isEmpty()) {
                if (!this.moveItemStackTo(ben5, 0, 2, false)) {
                    return ItemStack.EMPTY;
                }
            }
            else if (integer >= 3 && integer < 30) {
                if (!this.moveItemStackTo(ben5, 30, 39, false)) {
                    return ItemStack.EMPTY;
                }
            }
            else if (integer >= 30 && integer < 39 && !this.moveItemStackTo(ben5, 3, 30, false)) {
                return ItemStack.EMPTY;
            }
            if (ben5.isEmpty()) {
                bca5.set(ItemStack.EMPTY);
            }
            else {
                bca5.setChanged();
            }
            if (ben5.getCount() == ben4.getCount()) {
                return ItemStack.EMPTY;
            }
            bca5.onTake(ayj, ben5);
        }
        return ben4;
    }
}
