package net.minecraft.world.inventory;

import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.util.Mth;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.Level;
import net.minecraft.world.entity.player.Inventory;
import java.util.Iterator;
import net.minecraft.world.Container;
import net.minecraft.world.level.block.Block;
import com.google.common.collect.Sets;
import com.google.common.collect.Lists;
import net.minecraft.world.entity.player.Player;
import java.util.Set;
import javax.annotation.Nullable;
import java.util.List;
import net.minecraft.world.item.ItemStack;
import net.minecraft.core.NonNullList;

public abstract class AbstractContainerMenu {
    private final NonNullList<ItemStack> lastSlots;
    public final List<Slot> slots;
    private final List<DataSlot> dataSlots;
    @Nullable
    private final MenuType<?> menuType;
    public final int containerId;
    private short changeUid;
    private int quickcraftType;
    private int quickcraftStatus;
    private final Set<Slot> quickcraftSlots;
    private final List<ContainerListener> containerListeners;
    private final Set<Player> unSynchedPlayers;
    
    protected AbstractContainerMenu(@Nullable final MenuType<?> bbo, final int integer) {
        this.lastSlots = NonNullList.<ItemStack>create();
        this.slots = Lists.newArrayList();
        this.dataSlots = Lists.newArrayList();
        this.quickcraftType = -1;
        this.quickcraftSlots = Sets.newHashSet();
        this.containerListeners = Lists.newArrayList();
        this.unSynchedPlayers = Sets.newHashSet();
        this.menuType = bbo;
        this.containerId = integer;
    }
    
    protected static boolean stillValid(final ContainerLevelAccess bax, final Player ayj, final Block bph) {
        return bax.<Boolean>evaluate((bjw, fk) -> {
            if (bjw.getBlockState(fk).getBlock() != bph) {
                return false;
            }
            else {
                return ayj.distanceToSqr(fk.getX() + 0.5, fk.getY() + 0.5, fk.getZ() + 0.5) <= 64.0;
            }
        }, Boolean.valueOf(true));
    }
    
    public MenuType<?> getType() {
        if (this.menuType == null) {
            throw new UnsupportedOperationException("Unable to construct this menu by type");
        }
        return this.menuType;
    }
    
    protected static void checkContainerSize(final Container aje, final int integer) {
        final int integer2 = aje.getContainerSize();
        if (integer2 < integer) {
            throw new IllegalArgumentException("Container size " + integer2 + " is smaller than expected " + integer);
        }
    }
    
    protected static void checkContainerDataCount(final ContainerData baw, final int integer) {
        final int integer2 = baw.getCount();
        if (integer2 < integer) {
            throw new IllegalArgumentException("Container data count " + integer2 + " is smaller than expected " + integer);
        }
    }
    
    protected Slot addSlot(final Slot bca) {
        bca.index = this.slots.size();
        this.slots.add(bca);
        this.lastSlots.add(ItemStack.EMPTY);
        return bca;
    }
    
    protected DataSlot addDataSlot(final DataSlot bbb) {
        this.dataSlots.add(bbb);
        return bbb;
    }
    
    protected void addDataSlots(final ContainerData baw) {
        for (int integer3 = 0; integer3 < baw.getCount(); ++integer3) {
            this.addDataSlot(DataSlot.forContainer(baw, integer3));
        }
    }
    
    public void addSlotListener(final ContainerListener bay) {
        if (this.containerListeners.contains(bay)) {
            return;
        }
        this.containerListeners.add(bay);
        bay.refreshContainer(this, this.getItems());
        this.broadcastChanges();
    }
    
    public void removeSlotListener(final ContainerListener bay) {
        this.containerListeners.remove(bay);
    }
    
    public NonNullList<ItemStack> getItems() {
        final NonNullList<ItemStack> fy2 = NonNullList.<ItemStack>create();
        for (int integer3 = 0; integer3 < this.slots.size(); ++integer3) {
            fy2.add(this.slots.get(integer3).getItem());
        }
        return fy2;
    }
    
    public void broadcastChanges() {
        for (int integer2 = 0; integer2 < this.slots.size(); ++integer2) {
            final ItemStack ben3 = this.slots.get(integer2).getItem();
            ItemStack ben4 = this.lastSlots.get(integer2);
            if (!ItemStack.matches(ben4, ben3)) {
                ben4 = ben3.copy();
                this.lastSlots.set(integer2, ben4);
                for (final ContainerListener bay6 : this.containerListeners) {
                    bay6.slotChanged(this, integer2, ben4);
                }
            }
        }
        for (int integer2 = 0; integer2 < this.dataSlots.size(); ++integer2) {
            final DataSlot bbb3 = this.dataSlots.get(integer2);
            if (bbb3.checkAndClearUpdateFlag()) {
                for (final ContainerListener bay7 : this.containerListeners) {
                    bay7.setContainerData(this, integer2, bbb3.get());
                }
            }
        }
    }
    
    public boolean clickMenuButton(final Player ayj, final int integer) {
        return false;
    }
    
    public Slot getSlot(final int integer) {
        return this.slots.get(integer);
    }
    
    public ItemStack quickMoveStack(final Player ayj, final int integer) {
        final Slot bca4 = this.slots.get(integer);
        if (bca4 != null) {
            return bca4.getItem();
        }
        return ItemStack.EMPTY;
    }
    
    public ItemStack clicked(final int integer1, final int integer2, final ClickType bav, final Player ayj) {
        ItemStack ben6 = ItemStack.EMPTY;
        final Inventory ayi7 = ayj.inventory;
        if (bav == ClickType.QUICK_CRAFT) {
            final int integer3 = this.quickcraftStatus;
            this.quickcraftStatus = getQuickcraftHeader(integer2);
            if ((integer3 != 1 || this.quickcraftStatus != 2) && integer3 != this.quickcraftStatus) {
                this.resetQuickCraft();
            }
            else if (ayi7.getCarried().isEmpty()) {
                this.resetQuickCraft();
            }
            else if (this.quickcraftStatus == 0) {
                this.quickcraftType = getQuickcraftType(integer2);
                if (isValidQuickcraftType(this.quickcraftType, ayj)) {
                    this.quickcraftStatus = 1;
                    this.quickcraftSlots.clear();
                }
                else {
                    this.resetQuickCraft();
                }
            }
            else if (this.quickcraftStatus == 1) {
                final Slot bca9 = this.slots.get(integer1);
                final ItemStack ben7 = ayi7.getCarried();
                if (bca9 != null && canItemQuickReplace(bca9, ben7, true) && bca9.mayPlace(ben7) && (this.quickcraftType == 2 || ben7.getCount() > this.quickcraftSlots.size()) && this.canDragTo(bca9)) {
                    this.quickcraftSlots.add(bca9);
                }
            }
            else if (this.quickcraftStatus == 2) {
                if (!this.quickcraftSlots.isEmpty()) {
                    final ItemStack ben8 = ayi7.getCarried().copy();
                    int integer4 = ayi7.getCarried().getCount();
                    for (final Slot bca10 : this.quickcraftSlots) {
                        final ItemStack ben9 = ayi7.getCarried();
                        if (bca10 != null && canItemQuickReplace(bca10, ben9, true) && bca10.mayPlace(ben9) && (this.quickcraftType == 2 || ben9.getCount() >= this.quickcraftSlots.size()) && this.canDragTo(bca10)) {
                            final ItemStack ben10 = ben8.copy();
                            final int integer5 = bca10.hasItem() ? bca10.getItem().getCount() : 0;
                            getQuickCraftSlotCount(this.quickcraftSlots, this.quickcraftType, ben10, integer5);
                            final int integer6 = Math.min(ben10.getMaxStackSize(), bca10.getMaxStackSize(ben10));
                            if (ben10.getCount() > integer6) {
                                ben10.setCount(integer6);
                            }
                            integer4 -= ben10.getCount() - integer5;
                            bca10.set(ben10);
                        }
                    }
                    ben8.setCount(integer4);
                    ayi7.setCarried(ben8);
                }
                this.resetQuickCraft();
            }
            else {
                this.resetQuickCraft();
            }
        }
        else if (this.quickcraftStatus != 0) {
            this.resetQuickCraft();
        }
        else if ((bav == ClickType.PICKUP || bav == ClickType.QUICK_MOVE) && (integer2 == 0 || integer2 == 1)) {
            if (integer1 == -999) {
                if (!ayi7.getCarried().isEmpty()) {
                    if (integer2 == 0) {
                        ayj.drop(ayi7.getCarried(), true);
                        ayi7.setCarried(ItemStack.EMPTY);
                    }
                    if (integer2 == 1) {
                        ayj.drop(ayi7.getCarried().split(1), true);
                    }
                }
            }
            else if (bav == ClickType.QUICK_MOVE) {
                if (integer1 < 0) {
                    return ItemStack.EMPTY;
                }
                final Slot bca11 = this.slots.get(integer1);
                if (bca11 == null || !bca11.mayPickup(ayj)) {
                    return ItemStack.EMPTY;
                }
                for (ItemStack ben8 = this.quickMoveStack(ayj, integer1); !ben8.isEmpty() && ItemStack.isSame(bca11.getItem(), ben8); ben8 = this.quickMoveStack(ayj, integer1)) {
                    ben6 = ben8.copy();
                }
            }
            else {
                if (integer1 < 0) {
                    return ItemStack.EMPTY;
                }
                final Slot bca11 = this.slots.get(integer1);
                if (bca11 != null) {
                    ItemStack ben8 = bca11.getItem();
                    final ItemStack ben7 = ayi7.getCarried();
                    if (!ben8.isEmpty()) {
                        ben6 = ben8.copy();
                    }
                    if (ben8.isEmpty()) {
                        if (!ben7.isEmpty() && bca11.mayPlace(ben7)) {
                            int integer7 = (integer2 == 0) ? ben7.getCount() : 1;
                            if (integer7 > bca11.getMaxStackSize(ben7)) {
                                integer7 = bca11.getMaxStackSize(ben7);
                            }
                            bca11.set(ben7.split(integer7));
                        }
                    }
                    else if (bca11.mayPickup(ayj)) {
                        if (ben7.isEmpty()) {
                            if (ben8.isEmpty()) {
                                bca11.set(ItemStack.EMPTY);
                                ayi7.setCarried(ItemStack.EMPTY);
                            }
                            else {
                                final int integer7 = (integer2 == 0) ? ben8.getCount() : ((ben8.getCount() + 1) / 2);
                                ayi7.setCarried(bca11.remove(integer7));
                                if (ben8.isEmpty()) {
                                    bca11.set(ItemStack.EMPTY);
                                }
                                bca11.onTake(ayj, ayi7.getCarried());
                            }
                        }
                        else if (bca11.mayPlace(ben7)) {
                            if (consideredTheSameItem(ben8, ben7)) {
                                int integer7 = (integer2 == 0) ? ben7.getCount() : 1;
                                if (integer7 > bca11.getMaxStackSize(ben7) - ben8.getCount()) {
                                    integer7 = bca11.getMaxStackSize(ben7) - ben8.getCount();
                                }
                                if (integer7 > ben7.getMaxStackSize() - ben8.getCount()) {
                                    integer7 = ben7.getMaxStackSize() - ben8.getCount();
                                }
                                ben7.shrink(integer7);
                                ben8.grow(integer7);
                            }
                            else if (ben7.getCount() <= bca11.getMaxStackSize(ben7)) {
                                bca11.set(ben7);
                                ayi7.setCarried(ben8);
                            }
                        }
                        else if (ben7.getMaxStackSize() > 1 && consideredTheSameItem(ben8, ben7) && !ben8.isEmpty()) {
                            final int integer7 = ben8.getCount();
                            if (integer7 + ben7.getCount() <= ben7.getMaxStackSize()) {
                                ben7.grow(integer7);
                                ben8 = bca11.remove(integer7);
                                if (ben8.isEmpty()) {
                                    bca11.set(ItemStack.EMPTY);
                                }
                                bca11.onTake(ayj, ayi7.getCarried());
                            }
                        }
                    }
                    bca11.setChanged();
                }
            }
        }
        else if (bav == ClickType.SWAP && integer2 >= 0 && integer2 < 9) {
            final Slot bca11 = this.slots.get(integer1);
            final ItemStack ben8 = ayi7.getItem(integer2);
            final ItemStack ben7 = bca11.getItem();
            if (!ben8.isEmpty() || !ben7.isEmpty()) {
                if (ben8.isEmpty()) {
                    if (bca11.mayPickup(ayj)) {
                        ayi7.setItem(integer2, ben7);
                        bca11.onSwapCraft(ben7.getCount());
                        bca11.set(ItemStack.EMPTY);
                        bca11.onTake(ayj, ben7);
                    }
                }
                else if (ben7.isEmpty()) {
                    if (bca11.mayPlace(ben8)) {
                        final int integer7 = bca11.getMaxStackSize(ben8);
                        if (ben8.getCount() > integer7) {
                            bca11.set(ben8.split(integer7));
                        }
                        else {
                            bca11.set(ben8);
                            ayi7.setItem(integer2, ItemStack.EMPTY);
                        }
                    }
                }
                else if (bca11.mayPickup(ayj) && bca11.mayPlace(ben8)) {
                    final int integer7 = bca11.getMaxStackSize(ben8);
                    if (ben8.getCount() > integer7) {
                        bca11.set(ben8.split(integer7));
                        bca11.onTake(ayj, ben7);
                        if (!ayi7.add(ben7)) {
                            ayj.drop(ben7, true);
                        }
                    }
                    else {
                        bca11.set(ben8);
                        ayi7.setItem(integer2, ben7);
                        bca11.onTake(ayj, ben7);
                    }
                }
            }
        }
        else if (bav == ClickType.CLONE && ayj.abilities.instabuild && ayi7.getCarried().isEmpty() && integer1 >= 0) {
            final Slot bca11 = this.slots.get(integer1);
            if (bca11 != null && bca11.hasItem()) {
                final ItemStack ben8 = bca11.getItem().copy();
                ben8.setCount(ben8.getMaxStackSize());
                ayi7.setCarried(ben8);
            }
        }
        else if (bav == ClickType.THROW && ayi7.getCarried().isEmpty() && integer1 >= 0) {
            final Slot bca11 = this.slots.get(integer1);
            if (bca11 != null && bca11.hasItem() && bca11.mayPickup(ayj)) {
                final ItemStack ben8 = bca11.remove((integer2 == 0) ? 1 : bca11.getItem().getCount());
                bca11.onTake(ayj, ben8);
                ayj.drop(ben8, true);
            }
        }
        else if (bav == ClickType.PICKUP_ALL && integer1 >= 0) {
            final Slot bca11 = this.slots.get(integer1);
            final ItemStack ben8 = ayi7.getCarried();
            if (!ben8.isEmpty() && (bca11 == null || !bca11.hasItem() || !bca11.mayPickup(ayj))) {
                final int integer4 = (integer2 == 0) ? 0 : (this.slots.size() - 1);
                final int integer7 = (integer2 == 0) ? 1 : -1;
                for (int integer8 = 0; integer8 < 2; ++integer8) {
                    for (int integer9 = integer4; integer9 >= 0 && integer9 < this.slots.size() && ben8.getCount() < ben8.getMaxStackSize(); integer9 += integer7) {
                        final Slot bca12 = this.slots.get(integer9);
                        if (bca12.hasItem() && canItemQuickReplace(bca12, ben8, true) && bca12.mayPickup(ayj) && this.canTakeItemForPickAll(ben8, bca12)) {
                            final ItemStack ben11 = bca12.getItem();
                            if (integer8 != 0 || ben11.getCount() != ben11.getMaxStackSize()) {
                                final int integer6 = Math.min(ben8.getMaxStackSize() - ben8.getCount(), ben11.getCount());
                                final ItemStack ben12 = bca12.remove(integer6);
                                ben8.grow(integer6);
                                if (ben12.isEmpty()) {
                                    bca12.set(ItemStack.EMPTY);
                                }
                                bca12.onTake(ayj, ben12);
                            }
                        }
                    }
                }
            }
            this.broadcastChanges();
        }
        return ben6;
    }
    
    public static boolean consideredTheSameItem(final ItemStack ben1, final ItemStack ben2) {
        return ben1.getItem() == ben2.getItem() && ItemStack.tagMatches(ben1, ben2);
    }
    
    public boolean canTakeItemForPickAll(final ItemStack ben, final Slot bca) {
        return true;
    }
    
    public void removed(final Player ayj) {
        final Inventory ayi3 = ayj.inventory;
        if (!ayi3.getCarried().isEmpty()) {
            ayj.drop(ayi3.getCarried(), false);
            ayi3.setCarried(ItemStack.EMPTY);
        }
    }
    
    protected void clearContainer(final Player ayj, final Level bjw, final Container aje) {
        if (!ayj.isAlive() || (ayj instanceof ServerPlayer && ((ServerPlayer)ayj).hasDisconnected())) {
            for (int integer5 = 0; integer5 < aje.getContainerSize(); ++integer5) {
                ayj.drop(aje.removeItemNoUpdate(integer5), false);
            }
            return;
        }
        for (int integer5 = 0; integer5 < aje.getContainerSize(); ++integer5) {
            ayj.inventory.placeItemBackInInventory(bjw, aje.removeItemNoUpdate(integer5));
        }
    }
    
    public void slotsChanged(final Container aje) {
        this.broadcastChanges();
    }
    
    public void setItem(final int integer, final ItemStack ben) {
        this.getSlot(integer).set(ben);
    }
    
    public void setAll(final List<ItemStack> list) {
        for (int integer3 = 0; integer3 < list.size(); ++integer3) {
            this.getSlot(integer3).set(list.get(integer3));
        }
    }
    
    public void setData(final int integer1, final int integer2) {
        this.dataSlots.get(integer1).set(integer2);
    }
    
    public short backup(final Inventory ayi) {
        return (short)(++this.changeUid);
    }
    
    public boolean isSynched(final Player ayj) {
        return !this.unSynchedPlayers.contains(ayj);
    }
    
    public void setSynched(final Player ayj, final boolean boolean2) {
        if (boolean2) {
            this.unSynchedPlayers.remove(ayj);
        }
        else {
            this.unSynchedPlayers.add(ayj);
        }
    }
    
    public abstract boolean stillValid(final Player ayj);
    
    protected boolean moveItemStackTo(final ItemStack ben, final int integer2, final int integer3, final boolean boolean4) {
        boolean boolean5 = false;
        int integer4 = integer2;
        if (boolean4) {
            integer4 = integer3 - 1;
        }
        if (ben.isStackable()) {
            while (!ben.isEmpty()) {
                if (boolean4) {
                    if (integer4 < integer2) {
                        break;
                    }
                }
                else if (integer4 >= integer3) {
                    break;
                }
                final Slot bca8 = this.slots.get(integer4);
                final ItemStack ben2 = bca8.getItem();
                if (!ben2.isEmpty() && consideredTheSameItem(ben, ben2)) {
                    final int integer5 = ben2.getCount() + ben.getCount();
                    if (integer5 <= ben.getMaxStackSize()) {
                        ben.setCount(0);
                        ben2.setCount(integer5);
                        bca8.setChanged();
                        boolean5 = true;
                    }
                    else if (ben2.getCount() < ben.getMaxStackSize()) {
                        ben.shrink(ben.getMaxStackSize() - ben2.getCount());
                        ben2.setCount(ben.getMaxStackSize());
                        bca8.setChanged();
                        boolean5 = true;
                    }
                }
                if (boolean4) {
                    --integer4;
                }
                else {
                    ++integer4;
                }
            }
        }
        if (!ben.isEmpty()) {
            if (boolean4) {
                integer4 = integer3 - 1;
            }
            else {
                integer4 = integer2;
            }
            while (true) {
                if (boolean4) {
                    if (integer4 < integer2) {
                        break;
                    }
                }
                else if (integer4 >= integer3) {
                    break;
                }
                final Slot bca8 = this.slots.get(integer4);
                final ItemStack ben2 = bca8.getItem();
                if (ben2.isEmpty() && bca8.mayPlace(ben)) {
                    if (ben.getCount() > bca8.getMaxStackSize()) {
                        bca8.set(ben.split(bca8.getMaxStackSize()));
                    }
                    else {
                        bca8.set(ben.split(ben.getCount()));
                    }
                    bca8.setChanged();
                    boolean5 = true;
                    break;
                }
                if (boolean4) {
                    --integer4;
                }
                else {
                    ++integer4;
                }
            }
        }
        return boolean5;
    }
    
    public static int getQuickcraftType(final int integer) {
        return integer >> 2 & 0x3;
    }
    
    public static int getQuickcraftHeader(final int integer) {
        return integer & 0x3;
    }
    
    public static int getQuickcraftMask(final int integer1, final int integer2) {
        return (integer1 & 0x3) | (integer2 & 0x3) << 2;
    }
    
    public static boolean isValidQuickcraftType(final int integer, final Player ayj) {
        return integer == 0 || integer == 1 || (integer == 2 && ayj.abilities.instabuild);
    }
    
    protected void resetQuickCraft() {
        this.quickcraftStatus = 0;
        this.quickcraftSlots.clear();
    }
    
    public static boolean canItemQuickReplace(@Nullable final Slot bca, final ItemStack ben, final boolean boolean3) {
        final boolean boolean4 = bca == null || !bca.hasItem();
        if (!boolean4 && ben.sameItem(bca.getItem()) && ItemStack.tagMatches(bca.getItem(), ben)) {
            return bca.getItem().getCount() + (boolean3 ? 0 : ben.getCount()) <= ben.getMaxStackSize();
        }
        return boolean4;
    }
    
    public static void getQuickCraftSlotCount(final Set<Slot> set, final int integer2, final ItemStack ben, final int integer4) {
        switch (integer2) {
            case 0: {
                ben.setCount(Mth.floor(ben.getCount() / (float)set.size()));
                break;
            }
            case 1: {
                ben.setCount(1);
                break;
            }
            case 2: {
                ben.setCount(ben.getItem().getMaxStackSize());
                break;
            }
        }
        ben.grow(integer4);
    }
    
    public boolean canDragTo(final Slot bca) {
        return true;
    }
    
    public static int getRedstoneSignalFromBlockEntity(@Nullable final BlockEntity bwl) {
        if (bwl instanceof Container) {
            return getRedstoneSignalFromContainer((Container)bwl);
        }
        return 0;
    }
    
    public static int getRedstoneSignalFromContainer(@Nullable final Container aje) {
        if (aje == null) {
            return 0;
        }
        int integer2 = 0;
        float float3 = 0.0f;
        for (int integer3 = 0; integer3 < aje.getContainerSize(); ++integer3) {
            final ItemStack ben5 = aje.getItem(integer3);
            if (!ben5.isEmpty()) {
                float3 += ben5.getCount() / (float)Math.min(aje.getMaxStackSize(), ben5.getMaxStackSize());
                ++integer2;
            }
        }
        float3 /= aje.getContainerSize();
        return Mth.floor(float3 * 14.0f) + ((integer2 > 0) ? 1 : 0);
    }
}
