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

import java.util.Iterator;
import net.minecraft.world.level.levelgen.structure.StructurePiece;
import net.minecraft.world.level.levelgen.structure.MineShaftPieces;
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 java.util.stream.Collectors;
import java.util.Arrays;
import java.util.Map;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.WorldgenRandom;
import net.minecraft.world.level.biome.Biome;
import java.util.Random;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.biome.BiomeManager;
import com.mojang.datafixers.Dynamic;
import java.util.function.Function;
import net.minecraft.world.level.levelgen.feature.configurations.MineshaftConfiguration;

public class MineshaftFeature extends StructureFeature<MineshaftConfiguration> {
    public MineshaftFeature(final Function<Dynamic<?>, ? extends MineshaftConfiguration> function) {
        super(function);
    }
    
    @Override
    public boolean isFeatureChunk(final BiomeManager bkv, final ChunkGenerator<?> caa, final Random random, final int integer4, final int integer5, final Biome bkt) {
        ((WorldgenRandom)random).setLargeFeatureSeed(caa.getSeed(), integer4, integer5);
        if (caa.isBiomeValidStartForStructure(bkt, this)) {
            final MineshaftConfiguration cgs8 = caa.<MineshaftConfiguration>getStructureConfiguration(bkt, (StructureFeature<MineshaftConfiguration>)this);
            final double double9 = cgs8.probability;
            return random.nextDouble() < double9;
        }
        return false;
    }
    
    @Override
    public StructureStartFactory getStartFactory() {
        return MineShaftStart::new;
    }
    
    @Override
    public String getFeatureName() {
        return "Mineshaft";
    }
    
    @Override
    public int getLookupRange() {
        return 8;
    }
    
    public enum Type {
        NORMAL("normal"), 
        MESA("mesa");
        
        private static final Map<String, Type> BY_NAME;
        private final String name;
        
        private Type(final String string3) {
            this.name = string3;
        }
        
        public String getName() {
            return this.name;
        }
        
        public static Type byName(final String string) {
            return Type.BY_NAME.get(string);
        }
        
        public static Type byId(final int integer) {
            if (integer < 0 || integer >= values().length) {
                return Type.NORMAL;
            }
            return values()[integer];
        }
        
        static {
            BY_NAME = Arrays.<Type>stream(values()).collect(Collectors.toMap(Type::getName, b -> b));
        }
    }
    
    public static class MineShaftStart extends StructureStart {
        public MineShaftStart(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) {
            final MineshaftConfiguration cgs7 = caa.<MineshaftConfiguration>getStructureConfiguration(bkt, Feature.MINESHAFT);
            final MineShaftPieces.MineShaftRoom d8 = new MineShaftPieces.MineShaftRoom(0, this.random, (integer3 << 4) + 2, (integer4 << 4) + 2, cgs7.type);
            this.pieces.add(d8);
            d8.addChildren(d8, this.pieces, this.random);
            this.calculateBoundingBox();
            if (cgs7.type == Type.MESA) {
                final int integer5 = -5;
                final int integer6 = caa.getSeaLevel() - this.boundingBox.y1 + this.boundingBox.getYSpan() / 2 + 5;
                this.boundingBox.move(0, integer6, 0);
                for (final StructurePiece clu12 : this.pieces) {
                    clu12.move(0, integer6, 0);
                }
            }
            else {
                this.moveBelowSeaLevel(caa.getSeaLevel(), this.random, 10);
            }
        }
    }
}
