package net.minecraft.world.level.block.entity;

import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.core.NonNullList;
import java.util.List;
import net.minecraft.world.ContainerHelper;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.storage.loot.LootTable;
import net.minecraft.world.Container;
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
import net.minecraft.world.entity.Entity;
import net.minecraft.core.Vec3i;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.player.Player;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.core.BlockPos;
import java.util.Random;
import net.minecraft.world.level.BlockGetter;
import javax.annotation.Nullable;
import net.minecraft.resources.ResourceLocation;

public abstract class RandomizableContainerBlockEntity extends BaseContainerBlockEntity {
    @Nullable
    protected ResourceLocation lootTable;
    protected long lootTableSeed;
    
    protected RandomizableContainerBlockEntity(final BlockEntityType<?> bwm) {
        super(bwm);
    }
    
    public static void setLootTable(final BlockGetter bjg, final Random random, final BlockPos fk, final ResourceLocation sm) {
        final BlockEntity bwl5 = bjg.getBlockEntity(fk);
        if (bwl5 instanceof RandomizableContainerBlockEntity) {
            ((RandomizableContainerBlockEntity)bwl5).setLootTable(sm, random.nextLong());
        }
    }
    
    protected boolean tryLoadLootTable(final CompoundTag jt) {
        if (jt.contains("LootTable", 8)) {
            this.lootTable = new ResourceLocation(jt.getString("LootTable"));
            this.lootTableSeed = jt.getLong("LootTableSeed");
            return true;
        }
        return false;
    }
    
    protected boolean trySaveLootTable(final CompoundTag jt) {
        if (this.lootTable == null) {
            return false;
        }
        jt.putString("LootTable", this.lootTable.toString());
        if (this.lootTableSeed != 0L) {
            jt.putLong("LootTableSeed", this.lootTableSeed);
        }
        return true;
    }
    
    public void unpackLootTable(@Nullable final Player ayj) {
        if (this.lootTable != null && this.level.getServer() != null) {
            final LootTable csa3 = this.level.getServer().getLootTables().get(this.lootTable);
            this.lootTable = null;
            final LootContext.Builder a4 = new LootContext.Builder((ServerLevel)this.level).<BlockPos>withParameter(LootContextParams.BLOCK_POS, new BlockPos(this.worldPosition)).withOptionalRandomSeed(this.lootTableSeed);
            if (ayj != null) {
                a4.withLuck(ayj.getLuck()).<Entity>withParameter(LootContextParams.THIS_ENTITY, ayj);
            }
            csa3.fill(this, a4.create(LootContextParamSets.CHEST));
        }
    }
    
    public void setLootTable(final ResourceLocation sm, final long long2) {
        this.lootTable = sm;
        this.lootTableSeed = long2;
    }
    
    @Override
    public boolean isEmpty() {
        this.unpackLootTable(null);
        return this.getItems().stream().allMatch(ItemStack::isEmpty);
    }
    
    @Override
    public ItemStack getItem(final int integer) {
        this.unpackLootTable(null);
        return this.getItems().get(integer);
    }
    
    @Override
    public ItemStack removeItem(final int integer1, final int integer2) {
        this.unpackLootTable(null);
        final ItemStack ben4 = ContainerHelper.removeItem(this.getItems(), integer1, integer2);
        if (!ben4.isEmpty()) {
            this.setChanged();
        }
        return ben4;
    }
    
    @Override
    public ItemStack removeItemNoUpdate(final int integer) {
        this.unpackLootTable(null);
        return ContainerHelper.takeItem(this.getItems(), integer);
    }
    
    @Override
    public void setItem(final int integer, final ItemStack ben) {
        this.unpackLootTable(null);
        this.getItems().set(integer, ben);
        if (ben.getCount() > this.getMaxStackSize()) {
            ben.setCount(this.getMaxStackSize());
        }
        this.setChanged();
    }
    
    @Override
    public boolean stillValid(final Player ayj) {
        return this.level.getBlockEntity(this.worldPosition) == this && ayj.distanceToSqr(this.worldPosition.getX() + 0.5, this.worldPosition.getY() + 0.5, this.worldPosition.getZ() + 0.5) <= 64.0;
    }
    
    @Override
    public void clearContent() {
        this.getItems().clear();
    }
    
    protected abstract NonNullList<ItemStack> getItems();
    
    protected abstract void setItems(final NonNullList<ItemStack> fy);
    
    @Override
    public boolean canOpen(final Player ayj) {
        return super.canOpen(ayj) && (this.lootTable == null || !ayj.isSpectator());
    }
    
    @Nullable
    @Override
    public AbstractContainerMenu createMenu(final int integer, final Inventory ayi, final Player ayj) {
        if (this.canOpen(ayj)) {
            this.unpackLootTable(ayi.player);
            return this.createMenu(integer, ayi);
        }
        return null;
    }
}
