package net.minecraft.world.level.chunk;

import org.apache.logging.log4j.LogManager;
import net.minecraft.util.Mth;
import javax.annotation.Nullable;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.biome.Biomes;
import net.minecraft.core.Registry;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.level.biome.Biome;
import org.apache.logging.log4j.Logger;
import net.minecraft.world.level.biome.BiomeManager;

public class ChunkBiomeContainer implements BiomeManager.NoiseBiomeSource {
    private static final Logger LOGGER;
    private static final int WIDTH_BITS;
    private static final int HEIGHT_BITS;
    public static final int BIOMES_SIZE;
    public static final int HORIZONTAL_MASK;
    public static final int VERTICAL_MASK;
    private final Biome[] biomes;
    
    public ChunkBiomeContainer(final Biome[] arr) {
        this.biomes = arr;
    }
    
    private ChunkBiomeContainer() {
        this(new Biome[ChunkBiomeContainer.BIOMES_SIZE]);
    }
    
    public ChunkBiomeContainer(final FriendlyByteBuf mg) {
        this();
        for (int integer3 = 0; integer3 < this.biomes.length; ++integer3) {
            final int integer4 = mg.readInt();
            final Biome bre5 = Registry.BIOME.byId(integer4);
            if (bre5 == null) {
                ChunkBiomeContainer.LOGGER.warn("Received invalid biome id: " + integer4);
                this.biomes[integer3] = Biomes.PLAINS;
            }
            else {
                this.biomes[integer3] = bre5;
            }
        }
    }
    
    public ChunkBiomeContainer(final ChunkPos bph, final BiomeSource brh) {
        this();
        final int integer4 = bph.getMinBlockX() >> 2;
        final int integer5 = bph.getMinBlockZ() >> 2;
        for (int integer6 = 0; integer6 < this.biomes.length; ++integer6) {
            final int integer7 = integer6 & ChunkBiomeContainer.HORIZONTAL_MASK;
            final int integer8 = integer6 >> ChunkBiomeContainer.WIDTH_BITS + ChunkBiomeContainer.WIDTH_BITS & ChunkBiomeContainer.VERTICAL_MASK;
            final int integer9 = integer6 >> ChunkBiomeContainer.WIDTH_BITS & ChunkBiomeContainer.HORIZONTAL_MASK;
            this.biomes[integer6] = brh.getNoiseBiome(integer4 + integer7, integer8, integer5 + integer9);
        }
    }
    
    public ChunkBiomeContainer(final ChunkPos bph, final BiomeSource brh, @Nullable final int[] arr) {
        this();
        final int integer5 = bph.getMinBlockX() >> 2;
        final int integer6 = bph.getMinBlockZ() >> 2;
        if (arr != null) {
            for (int integer7 = 0; integer7 < arr.length; ++integer7) {
                this.biomes[integer7] = Registry.BIOME.byId(arr[integer7]);
                if (this.biomes[integer7] == null) {
                    final int integer8 = integer7 & ChunkBiomeContainer.HORIZONTAL_MASK;
                    final int integer9 = integer7 >> ChunkBiomeContainer.WIDTH_BITS + ChunkBiomeContainer.WIDTH_BITS & ChunkBiomeContainer.VERTICAL_MASK;
                    final int integer10 = integer7 >> ChunkBiomeContainer.WIDTH_BITS & ChunkBiomeContainer.HORIZONTAL_MASK;
                    this.biomes[integer7] = brh.getNoiseBiome(integer5 + integer8, integer9, integer6 + integer10);
                }
            }
        }
        else {
            for (int integer7 = 0; integer7 < this.biomes.length; ++integer7) {
                final int integer8 = integer7 & ChunkBiomeContainer.HORIZONTAL_MASK;
                final int integer9 = integer7 >> ChunkBiomeContainer.WIDTH_BITS + ChunkBiomeContainer.WIDTH_BITS & ChunkBiomeContainer.VERTICAL_MASK;
                final int integer10 = integer7 >> ChunkBiomeContainer.WIDTH_BITS & ChunkBiomeContainer.HORIZONTAL_MASK;
                this.biomes[integer7] = brh.getNoiseBiome(integer5 + integer8, integer9, integer6 + integer10);
            }
        }
    }
    
    public int[] writeBiomes() {
        final int[] arr2 = new int[this.biomes.length];
        for (int integer3 = 0; integer3 < this.biomes.length; ++integer3) {
            arr2[integer3] = Registry.BIOME.getId(this.biomes[integer3]);
        }
        return arr2;
    }
    
    public void write(final FriendlyByteBuf mg) {
        for (final Biome bre6 : this.biomes) {
            mg.writeInt(Registry.BIOME.getId(bre6));
        }
    }
    
    public ChunkBiomeContainer copy() {
        return new ChunkBiomeContainer(this.biomes.clone());
    }
    
    @Override
    public Biome getNoiseBiome(final int integer1, final int integer2, final int integer3) {
        final int integer4 = integer1 & ChunkBiomeContainer.HORIZONTAL_MASK;
        final int integer5 = Mth.clamp(integer2, 0, ChunkBiomeContainer.VERTICAL_MASK);
        final int integer6 = integer3 & ChunkBiomeContainer.HORIZONTAL_MASK;
        return this.biomes[integer5 << ChunkBiomeContainer.WIDTH_BITS + ChunkBiomeContainer.WIDTH_BITS | integer6 << ChunkBiomeContainer.WIDTH_BITS | integer4];
    }
    
    static {
        LOGGER = LogManager.getLogger();
        WIDTH_BITS = (int)Math.round(Math.log(16.0) / Math.log(2.0)) - 2;
        HEIGHT_BITS = (int)Math.round(Math.log(256.0) / Math.log(2.0)) - 2;
        BIOMES_SIZE = 1 << ChunkBiomeContainer.WIDTH_BITS + ChunkBiomeContainer.WIDTH_BITS + ChunkBiomeContainer.HEIGHT_BITS;
        HORIZONTAL_MASK = (1 << ChunkBiomeContainer.WIDTH_BITS) - 1;
        VERTICAL_MASK = (1 << ChunkBiomeContainer.HEIGHT_BITS) - 1;
    }
}
