package net.minecraft.world.level.levelgen.feature;

import net.minecraft.world.level.levelgen.ChunkGeneratorSettings;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.levelgen.structure.OceanMonumentPieces;
import net.minecraft.core.Direction;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
import net.minecraft.world.level.levelgen.structure.StructureStart;
import com.google.common.collect.Lists;
import net.minecraft.world.entity.EntityType;
import java.util.Iterator;
import java.util.Set;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.biome.BiomeManager;
import net.minecraft.world.level.levelgen.WorldgenRandom;
import net.minecraft.world.level.ChunkPos;
import java.util.Random;
import net.minecraft.world.level.chunk.ChunkGenerator;
import com.mojang.datafixers.Dynamic;
import java.util.function.Function;
import net.minecraft.world.level.biome.Biome;
import java.util.List;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;

public class OceanMonumentFeature extends StructureFeature<NoneFeatureConfiguration> {
    private static final List<Biome.SpawnerData> MONUMENT_ENEMIES;
    
    public OceanMonumentFeature(final Function<Dynamic<?>, ? extends NoneFeatureConfiguration> function) {
        super(function);
    }
    
    @Override
    protected ChunkPos getPotentialFeatureChunkFromLocationWithOffset(final ChunkGenerator<?> caa, final Random random, final int integer3, final int integer4, final int integer5, final int integer6) {
        final int integer7 = ((ChunkGeneratorSettings)caa.getSettings()).getMonumentsSpacing();
        final int integer8 = ((ChunkGeneratorSettings)caa.getSettings()).getMonumentsSeparation();
        final int integer9 = integer3 + integer7 * integer5;
        final int integer10 = integer4 + integer7 * integer6;
        final int integer11 = (integer9 < 0) ? (integer9 - integer7 + 1) : integer9;
        final int integer12 = (integer10 < 0) ? (integer10 - integer7 + 1) : integer10;
        int integer13 = integer11 / integer7;
        int integer14 = integer12 / integer7;
        ((WorldgenRandom)random).setLargeFeatureWithSalt(caa.getSeed(), integer13, integer14, 10387313);
        integer13 *= integer7;
        integer14 *= integer7;
        integer13 += (random.nextInt(integer7 - integer8) + random.nextInt(integer7 - integer8)) / 2;
        integer14 += (random.nextInt(integer7 - integer8) + random.nextInt(integer7 - integer8)) / 2;
        return new ChunkPos(integer13, integer14);
    }
    
    @Override
    public boolean isFeatureChunk(final BiomeManager bkv, final ChunkGenerator<?> caa, final Random random, final int integer4, final int integer5, final Biome bkt) {
        final ChunkPos bjh8 = this.getPotentialFeatureChunkFromLocationWithOffset(caa, random, integer4, integer5, 0, 0);
        if (integer4 == bjh8.x && integer5 == bjh8.z) {
            final Set<Biome> set9 = caa.getBiomeSource().getBiomesWithin(integer4 * 16 + 9, caa.getSeaLevel(), integer5 * 16 + 9, 16);
            for (final Biome bkt2 : set9) {
                if (!caa.isBiomeValidStartForStructure(bkt2, this)) {
                    return false;
                }
            }
            final Set<Biome> set10 = caa.getBiomeSource().getBiomesWithin(integer4 * 16 + 9, caa.getSeaLevel(), integer5 * 16 + 9, 29);
            for (final Biome bkt3 : set10) {
                if (bkt3.getBiomeCategory() != Biome.BiomeCategory.OCEAN && bkt3.getBiomeCategory() != Biome.BiomeCategory.RIVER) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }
    
    @Override
    public StructureStartFactory getStartFactory() {
        return OceanMonumentStart::new;
    }
    
    @Override
    public String getFeatureName() {
        return "Monument";
    }
    
    @Override
    public int getLookupRange() {
        return 8;
    }
    
    @Override
    public List<Biome.SpawnerData> getSpecialEnemies() {
        return OceanMonumentFeature.MONUMENT_ENEMIES;
    }
    
    static {
        MONUMENT_ENEMIES = Lists.<Biome.SpawnerData>newArrayList(new Biome.SpawnerData(EntityType.GUARDIAN, 1, 2, 4));
    }
    
    public static class OceanMonumentStart extends StructureStart {
        private boolean isCreated;
        
        public OceanMonumentStart(final StructureFeature<?> cfl, final int integer2, final int integer3, final BoundingBox clb, final int integer5, final long long6) {
            super(cfl, integer2, integer3, clb, integer5, long6);
        }
        
        @Override
        public void generatePieces(final ChunkGenerator<?> caa, final StructureManager cmo, final int integer3, final int integer4, final Biome bkt) {
            this.generatePieces(integer3, integer4);
        }
        
        private void generatePieces(final int integer1, final int integer2) {
            final int integer3 = integer1 * 16 - 29;
            final int integer4 = integer2 * 16 - 29;
            final Direction fp6 = Direction.Plane.HORIZONTAL.getRandomDirection(this.random);
            this.pieces.add(new OceanMonumentPieces.MonumentBuilding(this.random, integer3, integer4, fp6));
            this.calculateBoundingBox();
            this.isCreated = true;
        }
        
        @Override
        public void postProcess(final LevelAccessor bjx, final ChunkGenerator<?> caa, final Random random, final BoundingBox clb, final ChunkPos bjh) {
            if (!this.isCreated) {
                this.pieces.clear();
                this.generatePieces(this.getChunkX(), this.getChunkZ());
            }
            super.postProcess(bjx, caa, random, clb, bjh);
        }
    }
}
