package net.minecraft.world.inventory;

import org.apache.logging.log4j.LogManager;
import java.util.Iterator;
import java.util.Map;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import org.apache.commons.lang3.StringUtils;
import net.minecraft.world.item.enchantment.Enchantment;
import net.minecraft.world.item.EnchantedBookItem;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.AnvilBlock;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.Container;
import org.apache.logging.log4j.Logger;

public class AnvilMenu extends AbstractContainerMenu {
    private static final Logger LOGGER;
    private final Container resultSlots;
    private final Container repairSlots;
    private final DataSlot cost;
    private final ContainerLevelAccess access;
    private int repairItemCountCost;
    private String itemName;
    private final Player player;
    
    public AnvilMenu(final int integer, final Inventory ayi) {
        this(integer, ayi, ContainerLevelAccess.NULL);
    }
    
    public AnvilMenu(final int integer, final Inventory ayi, final ContainerLevelAccess bax) {
        super(MenuType.ANVIL, integer);
        this.resultSlots = new ResultContainer();
        this.repairSlots = new SimpleContainer(2) {
            @Override
            public void setChanged() {
                super.setChanged();
                AnvilMenu.this.slotsChanged(this);
            }
        };
        this.cost = DataSlot.standalone();
        this.access = bax;
        this.player = ayi.player;
        this.addDataSlot(this.cost);
        this.addSlot(new Slot(this.repairSlots, 0, 27, 47));
        this.addSlot(new Slot(this.repairSlots, 1, 76, 47));
        this.addSlot(new Slot(this.resultSlots, 2, 134, 47) {
            @Override
            public boolean mayPlace(final ItemStack ben) {
                return false;
            }
            
            @Override
            public boolean mayPickup(final Player ayj) {
                return (ayj.abilities.instabuild || ayj.experienceLevel >= AnvilMenu.this.cost.get()) && AnvilMenu.this.cost.get() > 0 && this.hasItem();
            }
            
            @Override
            public ItemStack onTake(final Player ayj, final ItemStack ben) {
                if (!ayj.abilities.instabuild) {
                    ayj.giveExperienceLevels(-AnvilMenu.this.cost.get());
                }
                AnvilMenu.this.repairSlots.setItem(0, ItemStack.EMPTY);
                if (AnvilMenu.this.repairItemCountCost > 0) {
                    final ItemStack ben2 = AnvilMenu.this.repairSlots.getItem(1);
                    if (!ben2.isEmpty() && ben2.getCount() > AnvilMenu.this.repairItemCountCost) {
                        ben2.shrink(AnvilMenu.this.repairItemCountCost);
                        AnvilMenu.this.repairSlots.setItem(1, ben2);
                    }
                    else {
                        AnvilMenu.this.repairSlots.setItem(1, ItemStack.EMPTY);
                    }
                }
                else {
                    AnvilMenu.this.repairSlots.setItem(1, ItemStack.EMPTY);
                }
                AnvilMenu.this.cost.set(0);
                final BlockState byj4;
                BlockState byj5;
                bax.execute((bjw, fk) -> {
                    byj4 = bjw.getBlockState(fk);
                    if (!ayj.abilities.instabuild && byj4.is(BlockTags.ANVIL) && ayj.getRandom().nextFloat() < 0.12f) {
                        byj5 = AnvilBlock.damage(byj4);
                        if (byj5 == null) {
                            bjw.removeBlock(fk, false);
                            bjw.levelEvent(1029, fk, 0);
                        }
                        else {
                            bjw.setBlock(fk, byj5, 2);
                            bjw.levelEvent(1030, fk, 0);
                        }
                    }
                    else {
                        bjw.levelEvent(1030, fk, 0);
                    }
                    return;
                });
                return ben;
            }
        });
        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();
        }
    }
    
    public void createResult() {
        final ItemStack ben2 = this.repairSlots.getItem(0);
        this.cost.set(1);
        int integer3 = 0;
        int integer4 = 0;
        int integer5 = 0;
        if (ben2.isEmpty()) {
            this.resultSlots.setItem(0, ItemStack.EMPTY);
            this.cost.set(0);
            return;
        }
        ItemStack ben3 = ben2.copy();
        final ItemStack ben4 = this.repairSlots.getItem(1);
        final Map<Enchantment, Integer> map8 = EnchantmentHelper.getEnchantments(ben3);
        integer4 += ben2.getBaseRepairCost() + (ben4.isEmpty() ? 0 : ben4.getBaseRepairCost());
        this.repairItemCountCost = 0;
        if (!ben4.isEmpty()) {
            final boolean boolean9 = ben4.getItem() == Items.ENCHANTED_BOOK && !EnchantedBookItem.getEnchantments(ben4).isEmpty();
            if (ben3.isDamageableItem() && ben3.getItem().isValidRepairItem(ben2, ben4)) {
                int integer6 = Math.min(ben3.getDamageValue(), ben3.getMaxDamage() / 4);
                if (integer6 <= 0) {
                    this.resultSlots.setItem(0, ItemStack.EMPTY);
                    this.cost.set(0);
                    return;
                }
                int integer7;
                for (integer7 = 0; integer6 > 0 && integer7 < ben4.getCount(); integer6 = Math.min(ben3.getDamageValue(), ben3.getMaxDamage() / 4), ++integer7) {
                    final int integer8 = ben3.getDamageValue() - integer6;
                    ben3.setDamageValue(integer8);
                    ++integer3;
                }
                this.repairItemCountCost = integer7;
            }
            else {
                if (!boolean9 && (ben3.getItem() != ben4.getItem() || !ben3.isDamageableItem())) {
                    this.resultSlots.setItem(0, ItemStack.EMPTY);
                    this.cost.set(0);
                    return;
                }
                if (ben3.isDamageableItem() && !boolean9) {
                    final int integer6 = ben2.getMaxDamage() - ben2.getDamageValue();
                    final int integer7 = ben4.getMaxDamage() - ben4.getDamageValue();
                    final int integer8 = integer7 + ben3.getMaxDamage() * 12 / 100;
                    final int integer9 = integer6 + integer8;
                    int integer10 = ben3.getMaxDamage() - integer9;
                    if (integer10 < 0) {
                        integer10 = 0;
                    }
                    if (integer10 < ben3.getDamageValue()) {
                        ben3.setDamageValue(integer10);
                        integer3 += 2;
                    }
                }
                final Map<Enchantment, Integer> map9 = EnchantmentHelper.getEnchantments(ben4);
                boolean boolean10 = false;
                boolean boolean11 = false;
                for (final Enchantment bhx14 : map9.keySet()) {
                    if (bhx14 == null) {
                        continue;
                    }
                    final int integer11 = map8.containsKey(bhx14) ? map8.get(bhx14) : 0;
                    int integer12 = map9.get(bhx14);
                    integer12 = ((integer11 == integer12) ? (integer12 + 1) : Math.max(integer12, integer11));
                    boolean boolean12 = bhx14.canEnchant(ben2);
                    if (this.player.abilities.instabuild || ben2.getItem() == Items.ENCHANTED_BOOK) {
                        boolean12 = true;
                    }
                    for (final Enchantment bhx15 : map8.keySet()) {
                        if (bhx15 != bhx14 && !bhx14.isCompatibleWith(bhx15)) {
                            boolean12 = false;
                            ++integer3;
                        }
                    }
                    if (!boolean12) {
                        boolean11 = true;
                    }
                    else {
                        boolean10 = true;
                        if (integer12 > bhx14.getMaxLevel()) {
                            integer12 = bhx14.getMaxLevel();
                        }
                        map8.put(bhx14, integer12);
                        int integer13 = 0;
                        switch (bhx14.getRarity()) {
                            case COMMON: {
                                integer13 = 1;
                                break;
                            }
                            case UNCOMMON: {
                                integer13 = 2;
                                break;
                            }
                            case RARE: {
                                integer13 = 4;
                                break;
                            }
                            case VERY_RARE: {
                                integer13 = 8;
                                break;
                            }
                        }
                        if (boolean9) {
                            integer13 = Math.max(1, integer13 / 2);
                        }
                        integer3 += integer13 * integer12;
                        if (ben2.getCount() <= 1) {
                            continue;
                        }
                        integer3 = 40;
                    }
                }
                if (boolean11 && !boolean10) {
                    this.resultSlots.setItem(0, ItemStack.EMPTY);
                    this.cost.set(0);
                    return;
                }
            }
        }
        if (StringUtils.isBlank((CharSequence)this.itemName)) {
            if (ben2.hasCustomHoverName()) {
                integer5 = 1;
                integer3 += integer5;
                ben3.resetHoverName();
            }
        }
        else if (!this.itemName.equals(ben2.getHoverName().getString())) {
            integer5 = 1;
            integer3 += integer5;
            ben3.setHoverName(new TextComponent(this.itemName));
        }
        this.cost.set(integer4 + integer3);
        if (integer3 <= 0) {
            ben3 = ItemStack.EMPTY;
        }
        if (integer5 == integer3 && integer5 > 0 && this.cost.get() >= 40) {
            this.cost.set(39);
        }
        if (this.cost.get() >= 40 && !this.player.abilities.instabuild) {
            ben3 = ItemStack.EMPTY;
        }
        if (!ben3.isEmpty()) {
            int integer14 = ben3.getBaseRepairCost();
            if (!ben4.isEmpty() && integer14 < ben4.getBaseRepairCost()) {
                integer14 = ben4.getBaseRepairCost();
            }
            if (integer5 != integer3 || integer5 == 0) {
                integer14 = calculateIncreasedRepairCost(integer14);
            }
            ben3.setRepairCost(integer14);
            EnchantmentHelper.setEnchantments(map8, ben3);
        }
        this.resultSlots.setItem(0, ben3);
        this.broadcastChanges();
    }
    
    public static int calculateIncreasedRepairCost(final int integer) {
        return integer * 2 + 1;
    }
    
    @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 this.access.<Boolean>evaluate((bjw, fk) -> {
            if (!bjw.getBlockState(fk).is(BlockTags.ANVIL)) {
                return false;
            }
            else {
                return ayj.distanceToSqr(fk.getX() + 0.5, fk.getY() + 0.5, fk.getZ() + 0.5) <= 64.0;
            }
        }, Boolean.valueOf(true));
    }
    
    @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();
            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 (integer >= 3 && integer < 39 && !this.moveItemStackTo(ben5, 0, 2, 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;
    }
    
    public void setItemName(final String string) {
        this.itemName = string;
        if (this.getSlot(2).hasItem()) {
            final ItemStack ben3 = this.getSlot(2).getItem();
            if (StringUtils.isBlank((CharSequence)string)) {
                ben3.resetHoverName();
            }
            else {
                ben3.setHoverName(new TextComponent(this.itemName));
            }
        }
        this.createResult();
    }
    
    public int getCost() {
        return this.cost.get();
    }
    
    static {
        LOGGER = LogManager.getLogger();
    }
}
