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

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

import com.hypixel.hytale.server.worldgen.util.NoiseBlockArray;
import com.hypixel.hytale.math.util.MathUtil;
import com.hypixel.hytale.procedurallib.supplier.IDoubleCoordinateSupplier;
import javax.annotation.Nullable;
import com.hypixel.hytale.procedurallib.condition.ICoordinateCondition;
import java.util.Arrays;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.worldgen.util.BlockFluidEntry;

public class LayerContainer
{
    @Nonnull
    protected final BlockFluidEntry filling;
    protected final int fillingEnvironment;
    protected final StaticLayer[] staticLayers;
    protected final DynamicLayer[] dynamicLayers;
    
    public LayerContainer(final int filling, final int fillingEnvironment, final StaticLayer[] staticLayers, final DynamicLayer[] dynamicLayers) {
        this.filling = new BlockFluidEntry(filling, 0, 0);
        this.fillingEnvironment = fillingEnvironment;
        this.staticLayers = staticLayers;
        this.dynamicLayers = dynamicLayers;
    }
    
    public BlockFluidEntry getFilling() {
        return this.filling;
    }
    
    public int getFillingEnvironment() {
        return this.fillingEnvironment;
    }
    
    public StaticLayer[] getStaticLayers() {
        return this.staticLayers;
    }
    
    public DynamicLayer[] getDynamicLayers() {
        return this.dynamicLayers;
    }
    
    public BlockFluidEntry getTopBlockAt(final int seed, final int x, final int z) {
        for (final DynamicLayer layer : this.dynamicLayers) {
            final DynamicLayerEntry entry = layer.getActiveEntry(seed, x, z);
            if (entry != null) {
                return entry.blockArray.getTopBlockAt(seed, x, z);
            }
        }
        return this.filling;
    }
    
    @Nonnull
    @Override
    public String toString() {
        return "LayerContainer{filling=" + String.valueOf(this.filling) + ", staticLayers=" + Arrays.toString(this.staticLayers) + ", dynamicLayers=" + Arrays.toString(this.dynamicLayers);
    }
    
    public static class Layer<T extends LayerEntry>
    {
        protected final T[] entries;
        protected final ICoordinateCondition mapCondition;
        protected final int environmentId;
        
        public Layer(final T[] entries, final ICoordinateCondition mapCondition, final int environmentId) {
            this.entries = entries;
            this.mapCondition = mapCondition;
            this.environmentId = environmentId;
        }
        
        public int getEnvironmentId() {
            return this.environmentId;
        }
        
        @Nullable
        public T getActiveEntry(final int seed, final int x, final int z) {
            if (!this.mapCondition.eval(seed, x, z)) {
                return null;
            }
            for (final T entry : this.entries) {
                if (entry.isActive(seed, x, z)) {
                    return entry;
                }
            }
            return null;
        }
        
        @Nonnull
        @Override
        public String toString() {
            return "Layer{entries=" + Arrays.toString(this.entries);
        }
    }
    
    public static class StaticLayer extends Layer<StaticLayerEntry>
    {
        public StaticLayer(final StaticLayerEntry[] entries, final ICoordinateCondition mapCondition, final int environmentId) {
            super(entries, mapCondition, environmentId);
        }
        
        @Nonnull
        @Override
        public String toString() {
            return "StaticLayer{entries=" + Arrays.toString(this.entries);
        }
    }
    
    public static class DynamicLayer extends Layer<DynamicLayerEntry>
    {
        protected final IDoubleCoordinateSupplier offset;
        
        public DynamicLayer(final DynamicLayerEntry[] entries, final ICoordinateCondition mapCondition, final int environmentId, final IDoubleCoordinateSupplier offset) {
            super(entries, mapCondition, environmentId);
            this.offset = offset;
        }
        
        public int getOffset(final int seed, final int x, final int z) {
            return MathUtil.floor(this.offset.get(seed, x, z));
        }
        
        @Nonnull
        @Override
        public String toString() {
            return "DynamicLayer{entries=" + Arrays.toString(this.entries) + ", offset=" + String.valueOf(this.offset);
        }
    }
    
    public abstract static class LayerEntry
    {
        protected final NoiseBlockArray blockArray;
        protected final ICoordinateCondition mapCondition;
        
        public LayerEntry(final NoiseBlockArray blockArray, final ICoordinateCondition mapCondition) {
            this.blockArray = blockArray;
            this.mapCondition = mapCondition;
        }
        
        public boolean isActive(final int seed, final int x, final int z) {
            return this.mapCondition.eval(seed, x, z);
        }
        
        public NoiseBlockArray getBlockArray() {
            return this.blockArray;
        }
        
        @Nonnull
        @Override
        public String toString() {
            return "LayerEntry{blockArray=" + String.valueOf(this.blockArray) + ", mapCondition=" + String.valueOf(this.mapCondition);
        }
    }
    
    public static class StaticLayerEntry extends LayerEntry
    {
        protected final IDoubleCoordinateSupplier min;
        protected final IDoubleCoordinateSupplier max;
        
        public StaticLayerEntry(final NoiseBlockArray blockArray, final ICoordinateCondition mapCondition, final IDoubleCoordinateSupplier min, final IDoubleCoordinateSupplier max) {
            super(blockArray, mapCondition);
            this.min = min;
            this.max = max;
        }
        
        public int getMinInt(final int seed, final int x, final int z) {
            return MathUtil.floor(this.getMinValue(seed, x, z));
        }
        
        public double getMinValue(final int seed, final int x, final int z) {
            return this.min.get(seed, x, z);
        }
        
        public int getMaxInt(final int seed, final int x, final int z) {
            return MathUtil.floor(this.getMaxValue(seed, x, z));
        }
        
        public double getMaxValue(final int seed, final int x, final int z) {
            return this.max.get(seed, x, z);
        }
        
        @Nonnull
        @Override
        public String toString() {
            return "StaticLayerEntry{blockArray=" + String.valueOf(this.blockArray) + ", mapCondition=" + String.valueOf(this.mapCondition) + ", min=" + String.valueOf(this.min) + ", max=" + String.valueOf(this.max);
        }
    }
    
    public static class DynamicLayerEntry extends LayerEntry
    {
        public DynamicLayerEntry(final NoiseBlockArray blockArray, final ICoordinateCondition mapCondition) {
            super(blockArray, mapCondition);
        }
        
        @Nonnull
        @Override
        public String toString() {
            return "DynamicLayerEntry{blockArray=" + String.valueOf(this.blockArray) + ", mapCondition=" + String.valueOf(this.mapCondition);
        }
    }
}
