package net.minecraft.world.level.chunk;

import net.minecraft.network.FriendlyByteBuf;
import javax.annotation.Nullable;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;

public class LevelChunkSection {
    private static final Palette<BlockState> GLOBAL_BLOCKSTATE_PALETTE;
    private final int bottomBlockY;
    private short nonEmptyBlockCount;
    private short tickingBlockCount;
    private short tickingFluidCount;
    private final PalettedContainer<BlockState> states;
    
    public LevelChunkSection(final int integer) {
        this(integer, (short)0, (short)0, (short)0);
    }
    
    public LevelChunkSection(final int integer, final short short2, final short short3, final short short4) {
        this.bottomBlockY = integer;
        this.nonEmptyBlockCount = short2;
        this.tickingBlockCount = short3;
        this.tickingFluidCount = short4;
        this.states = new PalettedContainer<BlockState>(LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE, Block.BLOCK_STATE_REGISTRY, NbtUtils::readBlockState, NbtUtils::writeBlockState, Blocks.AIR.defaultBlockState());
    }
    
    public BlockState getBlockState(final int integer1, final int integer2, final int integer3) {
        return this.states.get(integer1, integer2, integer3);
    }
    
    public FluidState getFluidState(final int integer1, final int integer2, final int integer3) {
        return this.states.get(integer1, integer2, integer3).getFluidState();
    }
    
    public void acquire() {
        this.states.acquire();
    }
    
    public void release() {
        this.states.release();
    }
    
    public BlockState setBlockState(final int integer1, final int integer2, final int integer3, final BlockState byj) {
        return this.setBlockState(integer1, integer2, integer3, byj, true);
    }
    
    public BlockState setBlockState(final int integer1, final int integer2, final int integer3, final BlockState byj, final boolean boolean5) {
        BlockState byj2;
        if (boolean5) {
            byj2 = this.states.getAndSet(integer1, integer2, integer3, byj);
        }
        else {
            byj2 = this.states.getAndSetUnchecked(integer1, integer2, integer3, byj);
        }
        final FluidState coj8 = byj2.getFluidState();
        final FluidState coj9 = byj.getFluidState();
        if (!byj2.isAir()) {
            --this.nonEmptyBlockCount;
            if (byj2.isRandomlyTicking()) {
                --this.tickingBlockCount;
            }
        }
        if (!coj8.isEmpty()) {
            --this.tickingFluidCount;
        }
        if (!byj.isAir()) {
            ++this.nonEmptyBlockCount;
            if (byj.isRandomlyTicking()) {
                ++this.tickingBlockCount;
            }
        }
        if (!coj9.isEmpty()) {
            ++this.tickingFluidCount;
        }
        return byj2;
    }
    
    public boolean isEmpty() {
        return this.nonEmptyBlockCount == 0;
    }
    
    public static boolean isEmpty(@Nullable final LevelChunkSection cam) {
        return cam == LevelChunk.EMPTY_SECTION || cam.isEmpty();
    }
    
    public boolean isRandomlyTicking() {
        return this.isRandomlyTickingBlocks() || this.isRandomlyTickingFluids();
    }
    
    public boolean isRandomlyTickingBlocks() {
        return this.tickingBlockCount > 0;
    }
    
    public boolean isRandomlyTickingFluids() {
        return this.tickingFluidCount > 0;
    }
    
    public int bottomBlockY() {
        return this.bottomBlockY;
    }
    
    public void recalcBlockCounts() {
        this.nonEmptyBlockCount = 0;
        this.tickingBlockCount = 0;
        this.tickingFluidCount = 0;
        final FluidState coj4;
        this.states.count((byj, integer) -> {
            coj4 = byj.getFluidState();
            if (!byj.isAir()) {
                this.nonEmptyBlockCount += integer;
                if (byj.isRandomlyTicking()) {
                    this.tickingBlockCount += integer;
                }
            }
            if (!coj4.isEmpty()) {
                this.nonEmptyBlockCount += integer;
                if (coj4.isRandomlyTicking()) {
                    this.tickingFluidCount += integer;
                }
            }
        });
    }
    
    public PalettedContainer<BlockState> getStates() {
        return this.states;
    }
    
    public void read(final FriendlyByteBuf kv) {
        this.nonEmptyBlockCount = kv.readShort();
        this.states.read(kv);
    }
    
    public void write(final FriendlyByteBuf kv) {
        kv.writeShort(this.nonEmptyBlockCount);
        this.states.write(kv);
    }
    
    public int getSerializedSize() {
        return 2 + this.states.getSerializedSize();
    }
    
    public boolean maybeHas(final BlockState byj) {
        return this.states.maybeHas(byj);
    }
    
    static {
        GLOBAL_BLOCKSTATE_PALETTE = new GlobalPalette<BlockState>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState());
    }
}
