package net.minecraft.client.renderer.chunk;

import net.minecraft.world.level.ColorResolver;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.lighting.LevelLightEngine;
import net.minecraft.core.Direction;
import java.util.Iterator;
import javax.annotation.Nullable;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockAndTintGetter;

public class RenderChunkRegion implements BlockAndTintGetter {
    protected final int centerX;
    protected final int centerZ;
    protected final BlockPos start;
    protected final int xLength;
    protected final int yLength;
    protected final int zLength;
    protected final LevelChunk[][] chunks;
    protected final BlockState[] blockStates;
    protected final FluidState[] fluidStates;
    protected final Level level;
    
    @Nullable
    public static RenderChunkRegion createIfNotEmpty(final Level bqb, final BlockPos fu2, final BlockPos fu3, final int integer) {
        final int integer2 = fu2.getX() - integer >> 4;
        final int integer3 = fu2.getZ() - integer >> 4;
        final int integer4 = fu3.getX() + integer >> 4;
        final int integer5 = fu3.getZ() + integer >> 4;
        final LevelChunk[][] arr9 = new LevelChunk[integer4 - integer2 + 1][integer5 - integer3 + 1];
        for (int integer6 = integer2; integer6 <= integer4; ++integer6) {
            for (int integer7 = integer3; integer7 <= integer5; ++integer7) {
                arr9[integer6 - integer2][integer7 - integer3] = bqb.getChunk(integer6, integer7);
            }
        }
        if (isAllEmpty(fu2, fu3, integer2, integer3, arr9)) {
            return null;
        }
        int integer6 = 1;
        final BlockPos fu4 = fu2.offset(-1, -1, -1);
        final BlockPos fu5 = fu3.offset(1, 1, 1);
        return new RenderChunkRegion(bqb, integer2, integer3, arr9, fu4, fu5);
    }
    
    public static boolean isAllEmpty(final BlockPos fu1, final BlockPos fu2, final int integer3, final int integer4, final LevelChunk[][] arr) {
        for (int integer5 = fu1.getX() >> 4; integer5 <= fu2.getX() >> 4; ++integer5) {
            for (int integer6 = fu1.getZ() >> 4; integer6 <= fu2.getZ() >> 4; ++integer6) {
                final LevelChunk chj8 = arr[integer5 - integer3][integer6 - integer4];
                if (!chj8.isYSpaceEmpty(fu1.getY(), fu2.getY())) {
                    return false;
                }
            }
        }
        return true;
    }
    
    public RenderChunkRegion(final Level bqb, final int integer2, final int integer3, final LevelChunk[][] arr, final BlockPos fu5, final BlockPos fu6) {
        this.level = bqb;
        this.centerX = integer2;
        this.centerZ = integer3;
        this.chunks = arr;
        this.start = fu5;
        this.xLength = fu6.getX() - fu5.getX() + 1;
        this.yLength = fu6.getY() - fu5.getY() + 1;
        this.zLength = fu6.getZ() - fu5.getZ() + 1;
        this.blockStates = new BlockState[this.xLength * this.yLength * this.zLength];
        this.fluidStates = new FluidState[this.xLength * this.yLength * this.zLength];
        for (final BlockPos fu7 : BlockPos.betweenClosed(fu5, fu6)) {
            final int integer4 = (fu7.getX() >> 4) - integer2;
            final int integer5 = (fu7.getZ() >> 4) - integer3;
            final LevelChunk chj12 = arr[integer4][integer5];
            final int integer6 = this.index(fu7);
            this.blockStates[integer6] = chj12.getBlockState(fu7);
            this.fluidStates[integer6] = chj12.getFluidState(fu7);
        }
    }
    
    protected final int index(final BlockPos fu) {
        return this.index(fu.getX(), fu.getY(), fu.getZ());
    }
    
    protected int index(final int integer1, final int integer2, final int integer3) {
        final int integer4 = integer1 - this.start.getX();
        final int integer5 = integer2 - this.start.getY();
        final int integer6 = integer3 - this.start.getZ();
        return integer6 * this.xLength * this.yLength + integer5 * this.xLength + integer4;
    }
    
    @Override
    public BlockState getBlockState(final BlockPos fu) {
        return this.blockStates[this.index(fu)];
    }
    
    @Override
    public FluidState getFluidState(final BlockPos fu) {
        return this.fluidStates[this.index(fu)];
    }
    
    @Override
    public float getShade(final Direction fz, final boolean boolean2) {
        return this.level.getShade(fz, boolean2);
    }
    
    @Override
    public LevelLightEngine getLightEngine() {
        return this.level.getLightEngine();
    }
    
    @Nullable
    @Override
    public BlockEntity getBlockEntity(final BlockPos fu) {
        return this.getBlockEntity(fu, LevelChunk.EntityCreationType.IMMEDIATE);
    }
    
    @Nullable
    public BlockEntity getBlockEntity(final BlockPos fu, final LevelChunk.EntityCreationType a) {
        final int integer4 = (fu.getX() >> 4) - this.centerX;
        final int integer5 = (fu.getZ() >> 4) - this.centerZ;
        return this.chunks[integer4][integer5].getBlockEntity(fu, a);
    }
    
    @Override
    public int getBlockTint(final BlockPos fu, final ColorResolver colorResolver) {
        return this.level.getBlockTint(fu, colorResolver);
    }
}
