package net.minecraft.world.inventory;

import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.entity.player.StackedContents;
import java.util.Optional;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.CraftingRecipe;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.item.ItemStack;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.Level;
import net.minecraft.world.Container;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;

public class CraftingMenu extends RecipeBookMenu<CraftingContainer> {
    private final CraftingContainer craftSlots;
    private final ResultContainer resultSlots;
    private final ContainerLevelAccess access;
    private final Player player;
    
    public CraftingMenu(final int integer, final Inventory ayi) {
        this(integer, ayi, ContainerLevelAccess.NULL);
    }
    
    public CraftingMenu(final int integer, final Inventory ayi, final ContainerLevelAccess bax) {
        super(MenuType.CRAFTING, integer);
        this.craftSlots = new CraftingContainer(this, 3, 3);
        this.resultSlots = new ResultContainer();
        this.access = bax;
        this.player = ayi.player;
        this.addSlot(new ResultSlot(ayi.player, this.craftSlots, this.resultSlots, 0, 124, 35));
        for (int integer2 = 0; integer2 < 3; ++integer2) {
            for (int integer3 = 0; integer3 < 3; ++integer3) {
                this.addSlot(new Slot(this.craftSlots, integer3 + integer2 * 3, 30 + integer3 * 18, 17 + integer2 * 18));
            }
        }
        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));
        }
    }
    
    protected static void slotChangedCraftingGrid(final int integer, final Level bjw, final Player ayj, final CraftingContainer baz, final ResultContainer bbv) {
        if (bjw.isClientSide) {
            return;
        }
        final ServerPlayer xe6 = (ServerPlayer)ayj;
        ItemStack ben7 = ItemStack.EMPTY;
        final Optional<CraftingRecipe> optional8 = bjw.getServer().getRecipeManager().<CraftingContainer, CraftingRecipe>getRecipeFor(RecipeType.CRAFTING, baz, bjw);
        if (optional8.isPresent()) {
            final CraftingRecipe bgo9 = optional8.get();
            if (bbv.setRecipeUsed(bjw, xe6, bgo9)) {
                ben7 = bgo9.assemble(baz);
            }
        }
        bbv.setItem(0, ben7);
        xe6.connection.send(new ClientboundContainerSetSlotPacket(integer, 0, ben7));
    }
    
    @Override
    public void slotsChanged(final Container aje) {
        this.access.execute((bjw, fk) -> slotChangedCraftingGrid(this.containerId, bjw, this.player, this.craftSlots, this.resultSlots));
    }
    
    @Override
    public void fillCraftSlotsStackedContents(final StackedContents ayl) {
        this.craftSlots.fillStackedContents(ayl);
    }
    
    @Override
    public void clearCraftingContent() {
        this.craftSlots.clearContent();
        this.resultSlots.clearContent();
    }
    
    @Override
    public boolean recipeMatches(final Recipe<? super CraftingContainer> bgw) {
        return bgw.matches(this.craftSlots, this.player.level);
    }
    
    @Override
    public void removed(final Player ayj) {
        super.removed(ayj);
        this.access.execute((bjw, fk) -> this.clearContainer(ayj, bjw, this.craftSlots));
    }
    
    @Override
    public boolean stillValid(final Player ayj) {
        return AbstractContainerMenu.stillValid(this.access, ayj, Blocks.CRAFTING_TABLE);
    }
    
    @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 == 0) {
                final ItemStack ben7;
                this.access.execute((bjw, fk) -> ben7.getItem().onCraftedBy(ben7, bjw, ayj));
                if (!this.moveItemStackTo(ben5, 10, 46, true)) {
                    return ItemStack.EMPTY;
                }
                bca5.onQuickCraft(ben5, ben4);
            }
            else if (integer >= 10 && integer < 46) {
                if (!this.moveItemStackTo(ben5, 1, 10, false)) {
                    if (integer < 37) {
                        if (!this.moveItemStackTo(ben5, 37, 46, false)) {
                            return ItemStack.EMPTY;
                        }
                    }
                    else if (!this.moveItemStackTo(ben5, 10, 37, false)) {
                        return ItemStack.EMPTY;
                    }
                }
            }
            else if (!this.moveItemStackTo(ben5, 10, 46, false)) {
                return ItemStack.EMPTY;
            }
            if (ben5.isEmpty()) {
                bca5.set(ItemStack.EMPTY);
            }
            else {
                bca5.setChanged();
            }
            if (ben5.getCount() == ben4.getCount()) {
                return ItemStack.EMPTY;
            }
            final ItemStack ben6 = bca5.onTake(ayj, ben5);
            if (integer == 0) {
                ayj.drop(ben6, false);
            }
        }
        return ben4;
    }
    
    @Override
    public boolean canTakeItemForPickAll(final ItemStack ben, final Slot bca) {
        return bca.container != this.resultSlots && super.canTakeItemForPickAll(ben, bca);
    }
    
    @Override
    public int getResultSlotIndex() {
        return 0;
    }
    
    @Override
    public int getGridWidth() {
        return this.craftSlots.getWidth();
    }
    
    @Override
    public int getGridHeight() {
        return this.craftSlots.getHeight();
    }
    
    @Override
    public int getSize() {
        return 10;
    }
}
