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

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

import com.hypixel.hytale.procedurallib.condition.IBlockFluidCondition;
import com.hypixel.hytale.procedurallib.condition.ICoordinateRndCondition;
import com.hypixel.hytale.server.core.prefab.PrefabRotation;
import com.hypixel.hytale.server.worldgen.cave.shape.CaveNodeShape;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.server.worldgen.cave.element.CaveNode;
import java.util.Random;
import com.hypixel.hytale.procedurallib.supplier.IDoubleRange;
import com.hypixel.hytale.procedurallib.condition.ICoordinateCondition;
import com.hypixel.hytale.server.worldgen.cave.shape.CaveNodeShapeEnum;
import com.hypixel.hytale.server.worldgen.util.BlockFluidEntry;
import com.hypixel.hytale.common.map.IWeightedMap;
import javax.annotation.Nullable;
import com.hypixel.hytale.server.worldgen.cave.prefab.CavePrefabContainer;
import javax.annotation.Nonnull;

public class CaveNodeType
{
    public static final CaveNodeType[] EMPTY_ARRAY;
    @Nonnull
    private final String name;
    @Nullable
    private final CavePrefabContainer prefabContainer;
    @Nonnull
    private final IWeightedMap<BlockFluidEntry> fillings;
    @Nonnull
    private final CaveNodeShapeEnum.CaveNodeShapeGenerator shapeGenerator;
    @Nonnull
    private final ICoordinateCondition heightCondition;
    @Nullable
    private final IDoubleRange childrenCountBounds;
    @Nonnull
    private final CaveNodeCoverEntry[] covers;
    private final int priority;
    private final int environment;
    private CaveNodeChildEntry[] children;
    
    public CaveNodeType(@Nonnull final String name, @Nullable final CavePrefabContainer prefabContainer, @Nonnull final IWeightedMap<BlockFluidEntry> fillings, @Nonnull final CaveNodeShapeEnum.CaveNodeShapeGenerator shapeGenerator, @Nonnull final ICoordinateCondition heightCondition, @Nullable final IDoubleRange childrenCountBounds, @Nonnull final CaveNodeCoverEntry[] covers, final int priority, final int environment) {
        this.name = name;
        this.prefabContainer = prefabContainer;
        this.fillings = fillings;
        this.shapeGenerator = shapeGenerator;
        this.heightCondition = heightCondition;
        this.childrenCountBounds = childrenCountBounds;
        this.covers = covers;
        this.priority = priority;
        this.environment = environment;
    }
    
    @Nonnull
    public String getName() {
        return this.name;
    }
    
    @Nullable
    public CavePrefabContainer getPrefabContainer() {
        return this.prefabContainer;
    }
    
    public void setChildren(@Nonnull final CaveNodeChildEntry[] children) {
        this.children = children;
    }
    
    @Nonnull
    public ICoordinateCondition getHeightCondition() {
        return this.heightCondition;
    }
    
    @Nullable
    public IDoubleRange getChildrenCountBounds() {
        return this.childrenCountBounds;
    }
    
    @Nullable
    public BlockFluidEntry getFilling(@Nonnull final Random random) {
        return this.fillings.get(random);
    }
    
    @Nonnull
    public CaveNodeShape generateCaveNodeShape(final Random random, final CaveType caveType, final CaveNode parentNode, final CaveNodeChildEntry childEntry, final Vector3d origin, final float yaw, final float pitch) {
        return this.shapeGenerator.generateCaveNodeShape(random, caveType, parentNode, childEntry, origin, yaw, pitch);
    }
    
    @Nonnull
    public CaveNodeCoverEntry[] getCovers() {
        return this.covers;
    }
    
    @Nonnull
    public CaveNodeChildEntry[] getChildren() {
        return this.children;
    }
    
    public int getPriority() {
        return this.priority;
    }
    
    public boolean hasEnvironment() {
        return this.environment != Integer.MIN_VALUE;
    }
    
    public int getEnvironment() {
        return this.environment;
    }
    
    static {
        EMPTY_ARRAY = new CaveNodeType[0];
    }
    
    public static class CaveNodeChildEntry
    {
        public static final CaveNodeChildEntry[] EMPTY_ARRAY;
        @Nonnull
        private final IWeightedMap<CaveNodeType> types;
        @Nonnull
        private final Vector3d anchor;
        @Nonnull
        private final Vector3d offset;
        @Nonnull
        private final PrefabRotation[] rotation;
        @Nullable
        private final IDoubleRange childrenLimit;
        @Nonnull
        private final IDoubleRange repeat;
        @Nonnull
        private final OrientationModifier pitchModifier;
        @Nonnull
        private final OrientationModifier yawModifier;
        private final double chance;
        @Nonnull
        private final CaveYawMode yawMode;
        
        public CaveNodeChildEntry(@Nonnull final IWeightedMap<CaveNodeType> types, @Nonnull final Vector3d anchor, @Nonnull final Vector3d offset, @Nonnull final PrefabRotation[] rotation, @Nullable final IDoubleRange childrenLimit, @Nonnull final IDoubleRange repeat, @Nonnull final OrientationModifier pitchModifier, @Nonnull final OrientationModifier yawModifier, final double chance, @Nonnull final CaveYawMode yawMode) {
            this.types = types;
            this.anchor = anchor;
            this.offset = offset;
            this.rotation = rotation;
            this.childrenLimit = childrenLimit;
            this.repeat = repeat;
            this.pitchModifier = pitchModifier;
            this.yawModifier = yawModifier;
            this.chance = chance;
            this.yawMode = yawMode;
        }
        
        @Nonnull
        public IWeightedMap<CaveNodeType> getTypes() {
            return this.types;
        }
        
        @Nonnull
        public Vector3d getAnchor() {
            return this.anchor;
        }
        
        @Nonnull
        public Vector3d getOffset() {
            return this.offset;
        }
        
        @Nonnull
        public PrefabRotation getRotation(@Nonnull final Random random) {
            return (this.rotation.length == 1) ? this.rotation[0] : this.rotation[random.nextInt(this.rotation.length)];
        }
        
        @Nullable
        public IDoubleRange getChildrenLimit() {
            return this.childrenLimit;
        }
        
        @Nonnull
        public IDoubleRange getRepeat() {
            return this.repeat;
        }
        
        @Nonnull
        public OrientationModifier getPitchModifier() {
            return this.pitchModifier;
        }
        
        @Nonnull
        public OrientationModifier getYawModifier() {
            return this.yawModifier;
        }
        
        public double getChance() {
            return this.chance;
        }
        
        @Nonnull
        public CaveYawMode getYawMode() {
            return this.yawMode;
        }
        
        static {
            EMPTY_ARRAY = new CaveNodeChildEntry[0];
        }
        
        @FunctionalInterface
        public interface OrientationModifier
        {
            float calc(final float p0, final Random p1);
        }
    }
    
    public static class CaveNodeCoverEntry
    {
        public static final CaveNodeCoverEntry[] EMPTY_ARRAY;
        @Nonnull
        protected final IWeightedMap<Entry> entries;
        @Nonnull
        protected final ICoordinateRndCondition heightCondition;
        @Nonnull
        protected final ICoordinateCondition mapCondition;
        @Nonnull
        protected final ICoordinateCondition densityCondition;
        @Nonnull
        protected final IBlockFluidCondition parentCondition;
        @Nonnull
        protected final CaveNodeCoverType type;
        
        public CaveNodeCoverEntry(@Nonnull final IWeightedMap<Entry> entries, @Nonnull final ICoordinateRndCondition heightCondition, @Nonnull final ICoordinateCondition mapCondition, @Nonnull final ICoordinateCondition densityCondition, @Nonnull final IBlockFluidCondition parentCondition, @Nonnull final CaveNodeCoverType type) {
            this.entries = entries;
            this.heightCondition = heightCondition;
            this.mapCondition = mapCondition;
            this.densityCondition = densityCondition;
            this.type = type;
            this.parentCondition = parentCondition;
        }
        
        @Nullable
        public Entry get(final Random random) {
            return this.entries.get(random);
        }
        
        @Nonnull
        public ICoordinateRndCondition getHeightCondition() {
            return this.heightCondition;
        }
        
        @Nonnull
        public ICoordinateCondition getMapCondition() {
            return this.mapCondition;
        }
        
        @Nonnull
        public ICoordinateCondition getDensityCondition() {
            return this.densityCondition;
        }
        
        @Nonnull
        public IBlockFluidCondition getParentCondition() {
            return this.parentCondition;
        }
        
        @Nonnull
        public CaveNodeCoverType getType() {
            return this.type;
        }
        
        static {
            EMPTY_ARRAY = new CaveNodeCoverEntry[0];
        }
        
        public static class Entry
        {
            public static final Entry[] EMPTY_ARRAY;
            protected final BlockFluidEntry entry;
            protected final int offset;
            
            public Entry(final BlockFluidEntry entry, final int offset) {
                this.entry = entry;
                this.offset = offset;
            }
            
            public int getOffset() {
                return this.offset;
            }
            
            public BlockFluidEntry getEntry() {
                return this.entry;
            }
            
            @Nonnull
            @Override
            public String toString() {
                return "Entry{entry=" + String.valueOf(this.entry) + ", offset=" + this.offset;
            }
            
            static {
                EMPTY_ARRAY = new Entry[0];
            }
        }
    }
    
    public enum CaveNodeCoverType
    {
        FLOOR(-1), 
        CEILING(1);
        
        public final int parentOffset;
        
        private CaveNodeCoverType(final int parentOffset) {
            this.parentOffset = parentOffset;
        }
    }
}
