// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.server.worldgen.biome;

import java.util.Arrays;
import java.util.Objects;
import com.hypixel.hytale.server.worldgen.zone.ZoneGeneratorResult;
import com.hypixel.hytale.procedurallib.logic.ResultBuffer;
import com.hypixel.hytale.math.util.HashUtil;
import javax.annotation.Nullable;
import javax.annotation.Nonnull;
import com.hypixel.hytale.common.map.IWeightedMap;
import com.hypixel.hytale.procedurallib.logic.point.IPointGenerator;

public class BiomePatternGenerator
{
    protected final IPointGenerator pointGenerator;
    @Nonnull
    protected final IWeightedMap<TileBiome> tileBiomes;
    @Nonnull
    protected final CustomBiome[] customBiomes;
    @Nonnull
    protected final Biome[] biomes;
    protected final int extents;
    
    public BiomePatternGenerator(final IPointGenerator pointGenerator, @Nonnull final IWeightedMap<TileBiome> tileBiomes, @Nonnull final CustomBiome[] customBiomes) {
        this.pointGenerator = pointGenerator;
        this.tileBiomes = tileBiomes;
        this.customBiomes = customBiomes;
        this.biomes = new Biome[tileBiomes.size() + customBiomes.length];
        int n = 0;
        for (final TileBiome biome : tileBiomes.internalKeys()) {
            this.biomes[n++] = biome;
        }
        for (final CustomBiome biome2 : customBiomes) {
            this.biomes[n++] = biome2;
        }
        this.extents = getExtents(this.biomes);
    }
    
    public int getExtents() {
        return this.extents;
    }
    
    @Nonnull
    public Biome[] getBiomes() {
        return this.biomes;
    }
    
    @Nonnull
    public CustomBiome[] getCustomBiomes() {
        return this.customBiomes;
    }
    
    @Nullable
    public TileBiome getBiome(final int seed, final int x, final int z) {
        return this.tileBiomes.get(seed, x, z, (iSeed, ix, iz, generator) -> generator.getBiomeIndex(iSeed, ix, iz), this);
    }
    
    protected double getBiomeIndex(final int seed, final int x, final int z) {
        final ResultBuffer.ResultBuffer2d buf = this.pointGenerator.nearest2D(seed, x, z);
        return HashUtil.random(seed, buf.ix, buf.iy);
    }
    
    @Nullable
    public TileBiome getBiomeDirect(final int seed, final int x, final int z) {
        return this.tileBiomes.get(HashUtil.random(seed, Double.doubleToLongBits(x), Double.doubleToLongBits(z)));
    }
    
    @Nonnull
    public Biome generateBiomeAt(@Nonnull final ZoneGeneratorResult zoneResult, final int seed, final int x, final int z) {
        final TileBiome parentResult = this.getBiome(seed, x, z);
        final CustomBiome customBiome = this.getCustomBiomeAt(seed, x, z, zoneResult, parentResult);
        return Objects.requireNonNullElse(customBiome, parentResult);
    }
    
    @Nullable
    public CustomBiome getCustomBiomeAt(final int seed, final double x, final double z, @Nonnull final ZoneGeneratorResult zoneResult, @Nonnull final Biome parentResult) {
        if (this.customBiomes.length > 0) {
            final int parentBiomeIndex = parentResult.getId();
            for (final CustomBiome customBiome : this.customBiomes) {
                final CustomBiomeGenerator customBiomeGenerator = customBiome.getCustomBiomeGenerator();
                if (customBiomeGenerator.isValidParentBiome(parentBiomeIndex) && customBiomeGenerator.shouldGenerateAt(seed, x, z, zoneResult, customBiome)) {
                    return customBiome;
                }
            }
        }
        return null;
    }
    
    @Nonnull
    @Override
    public String toString() {
        return "BiomePatternGenerator{pointGenerator=" + String.valueOf(this.pointGenerator) + ", tileBiomes=" + String.valueOf(this.tileBiomes) + ", customBiomes=" + Arrays.toString(this.customBiomes) + ", biomes=" + Arrays.toString(this.biomes);
    }
    
    private static int getExtents(@Nonnull final Biome[] biomes) {
        int maxExtent = 0;
        for (final Biome biome : biomes) {
            if (biome.getPrefabContainer() != null) {
                maxExtent = Math.max(maxExtent, biome.getPrefabContainer().getMaxSize());
            }
        }
        return maxExtent;
    }
}
