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.advancements.CriteriaTriggers;
import net.minecraft.server.level.ServerPlayer;
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<?> cdm) {
        super(cdm);
    }
    
    public static void setLootTable(final BlockGetter bpg, final Random random, final BlockPos fu, final ResourceLocation uh) {
        final BlockEntity cdl5 = bpg.getBlockEntity(fu);
        if (cdl5 instanceof RandomizableContainerBlockEntity) {
            ((RandomizableContainerBlockEntity)cdl5).setLootTable(uh, random.nextLong());
        }
    }
    
    protected boolean tryLoadLootTable(final CompoundTag le) {
        if (le.contains("LootTable", 8)) {
            this.lootTable = new ResourceLocation(le.getString("LootTable"));
            this.lootTableSeed = le.getLong("LootTableSeed");
            return true;
        }
        return false;
    }
    
    protected boolean trySaveLootTable(final CompoundTag le) {
        if (this.lootTable == null) {
            return false;
        }
        le.putString("LootTable", this.lootTable.toString());
        if (this.lootTableSeed != 0L) {
            le.putLong("LootTableSeed", this.lootTableSeed);
        }
        return true;
    }
    
    public void unpackLootTable(@Nullable final Player bec) {
        if (this.lootTable != null && this.level.getServer() != null) {
            final LootTable daw3 = this.level.getServer().getLootTables().get(this.lootTable);
            if (bec instanceof ServerPlayer) {
                CriteriaTriggers.GENERATE_LOOT.trigger((ServerPlayer)bec, 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 (bec != null) {
                a4.withLuck(bec.getLuck()).<Entity>withParameter(LootContextParams.THIS_ENTITY, bec);
            }
            daw3.fill(this, a4.create(LootContextParamSets.CHEST));
        }
    }
    
    public void setLootTable(final ResourceLocation uh, final long long2) {
        this.lootTable = uh;
        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 bki4 = ContainerHelper.removeItem(this.getItems(), integer1, integer2);
        if (!bki4.isEmpty()) {
            this.setChanged();
        }
        return bki4;
    }
    
    @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 bki) {
        this.unpackLootTable(null);
        this.getItems().set(integer, bki);
        if (bki.getCount() > this.getMaxStackSize()) {
            bki.setCount(this.getMaxStackSize());
        }
        this.setChanged();
    }
    
    @Override
    public boolean stillValid(final Player bec) {
        return this.level.getBlockEntity(this.worldPosition) == this && bec.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> gi);
    
    @Override
    public boolean canOpen(final Player bec) {
        return super.canOpen(bec) && (this.lootTable == null || !bec.isSpectator());
    }
    
    @Nullable
    @Override
    public AbstractContainerMenu createMenu(final int integer, final Inventory beb, final Player bec) {
        if (this.canOpen(bec)) {
            this.unpackLootTable(beb.player);
            return this.createMenu(integer, beb);
        }
        return null;
    }
}
