package net.minecraft.world.level;

import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.phys.shapes.VoxelShape;
import java.util.stream.Stream;
import java.util.function.Predicate;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import javax.annotation.Nullable;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.border.WorldBorder;
import net.minecraft.world.level.chunk.EmptyLevelChunk;
import net.minecraft.world.level.chunk.ChunkSource;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.chunk.ChunkAccess;

public class PathNavigationRegion implements BlockGetter, CollisionGetter {
    protected final int centerX;
    protected final int centerZ;
    protected final ChunkAccess[][] chunks;
    protected boolean allEmpty;
    protected final Level level;
    
    public PathNavigationRegion(final Level bqb, final BlockPos fu2, final BlockPos fu3) {
        this.level = bqb;
        this.centerX = fu2.getX() >> 4;
        this.centerZ = fu2.getZ() >> 4;
        final int integer5 = fu3.getX() >> 4;
        final int integer6 = fu3.getZ() >> 4;
        this.chunks = new ChunkAccess[integer5 - this.centerX + 1][integer6 - this.centerZ + 1];
        final ChunkSource chb7 = bqb.getChunkSource();
        this.allEmpty = true;
        for (int integer7 = this.centerX; integer7 <= integer5; ++integer7) {
            for (int integer8 = this.centerZ; integer8 <= integer6; ++integer8) {
                this.chunks[integer7 - this.centerX][integer8 - this.centerZ] = chb7.getChunkNow(integer7, integer8);
            }
        }
        for (int integer7 = fu2.getX() >> 4; integer7 <= fu3.getX() >> 4; ++integer7) {
            for (int integer8 = fu2.getZ() >> 4; integer8 <= fu3.getZ() >> 4; ++integer8) {
                final ChunkAccess cgy10 = this.chunks[integer7 - this.centerX][integer8 - this.centerZ];
                if (cgy10 != null && !cgy10.isYSpaceEmpty(fu2.getY(), fu3.getY())) {
                    this.allEmpty = false;
                    return;
                }
            }
        }
    }
    
    private ChunkAccess getChunk(final BlockPos fu) {
        return this.getChunk(fu.getX() >> 4, fu.getZ() >> 4);
    }
    
    private ChunkAccess getChunk(final int integer1, final int integer2) {
        final int integer3 = integer1 - this.centerX;
        final int integer4 = integer2 - this.centerZ;
        if (integer3 < 0 || integer3 >= this.chunks.length || integer4 < 0 || integer4 >= this.chunks[integer3].length) {
            return new EmptyLevelChunk(this.level, new ChunkPos(integer1, integer2));
        }
        final ChunkAccess cgy6 = this.chunks[integer3][integer4];
        return (cgy6 != null) ? cgy6 : new EmptyLevelChunk(this.level, new ChunkPos(integer1, integer2));
    }
    
    @Override
    public WorldBorder getWorldBorder() {
        return this.level.getWorldBorder();
    }
    
    @Override
    public BlockGetter getChunkForCollisions(final int integer1, final int integer2) {
        return this.getChunk(integer1, integer2);
    }
    
    @Nullable
    @Override
    public BlockEntity getBlockEntity(final BlockPos fu) {
        final ChunkAccess cgy3 = this.getChunk(fu);
        return cgy3.getBlockEntity(fu);
    }
    
    @Override
    public BlockState getBlockState(final BlockPos fu) {
        if (Level.isOutsideBuildHeight(fu)) {
            return Blocks.AIR.defaultBlockState();
        }
        final ChunkAccess cgy3 = this.getChunk(fu);
        return cgy3.getBlockState(fu);
    }
    
    @Override
    public Stream<VoxelShape> getEntityCollisions(@Nullable final Entity aom, final AABB deg, final Predicate<Entity> predicate) {
        return Stream.<VoxelShape>empty();
    }
    
    @Override
    public Stream<VoxelShape> getCollisions(@Nullable final Entity aom, final AABB deg, final Predicate<Entity> predicate) {
        return this.getBlockCollisions(aom, deg);
    }
    
    @Override
    public FluidState getFluidState(final BlockPos fu) {
        if (Level.isOutsideBuildHeight(fu)) {
            return Fluids.EMPTY.defaultFluidState();
        }
        final ChunkAccess cgy3 = this.getChunk(fu);
        return cgy3.getFluidState(fu);
    }
}
