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

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

import it.unimi.dsi.fastutil.objects.ObjectIterator;
import it.unimi.dsi.fastutil.objects.ObjectArrays;
import java.util.ArrayList;
import com.hypixel.hytale.server.worldgen.util.bounds.IChunkBounds;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.worldgen.util.bounds.WorldBounds;
import javax.annotation.Nullable;
import java.util.List;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import com.hypixel.hytale.server.worldgen.cave.element.CaveNode;
import java.util.Comparator;

public class Cave
{
    private static final Comparator<CaveNode> ORDER;
    @Nullable
    private Long2ObjectMap<List<CaveNode>> rawChunkNodeMap;
    private Long2ObjectMap<CaveNode[]> chunkNodeMap;
    private final CaveType caveType;
    @Nonnull
    private final WorldBounds bounds;
    private int nodeCount;
    
    public Cave(final CaveType caveType) {
        this.rawChunkNodeMap = new Long2ObjectOpenHashMap<List<CaveNode>>();
        this.caveType = caveType;
        this.bounds = new WorldBounds();
        this.nodeCount = 0;
    }
    
    public long getNodeCount() {
        return this.nodeCount;
    }
    
    @Nonnull
    public CaveType getCaveType() {
        return this.caveType;
    }
    
    @Nonnull
    public WorldBounds getBounds() {
        return this.bounds;
    }
    
    public void addNode(@Nonnull final CaveNode element) {
        element.compile();
        this.bounds.include(element.getBounds());
        element.forEachChunk(chunk -> {
            List<CaveNode> nodes = this.rawChunkNodeMap.get(chunk);
            if (nodes == null) {
                final Long2ObjectMap<List<CaveNode>> rawChunkNodeMap = this.rawChunkNodeMap;
                nodes = new ArrayList<CaveNode>();
                final ArrayList value;
                rawChunkNodeMap.put(chunk, value);
            }
            nodes.add(element);
            return;
        });
        ++this.nodeCount;
    }
    
    public boolean contains(final long chunkIndex) {
        return this.chunkNodeMap.containsKey(chunkIndex);
    }
    
    public CaveNode[] getCaveNodes(final long chunkIndex) {
        return this.chunkNodeMap.get(chunkIndex);
    }
    
    public void compile() {
        this.compileNodeMap();
    }
    
    private void compileNodeMap() {
        this.chunkNodeMap = new Long2ObjectOpenHashMap<CaveNode[]>();
        for (final Long2ObjectMap.Entry<List<CaveNode>> entry : this.rawChunkNodeMap.long2ObjectEntrySet()) {
            final CaveNode[] array = (CaveNode[])entry.getValue().toArray(CaveNode[]::new);
            ObjectArrays.mergeSort(array, Cave.ORDER);
            this.chunkNodeMap.put(entry.getLongKey(), array);
        }
        this.rawChunkNodeMap = null;
    }
    
    @Nonnull
    @Override
    public String toString() {
        return "Cave{rawChunkNodeMap=" + String.valueOf(this.rawChunkNodeMap) + ", chunkNodeMap=" + String.valueOf(this.chunkNodeMap) + ", caveType=" + String.valueOf(this.caveType) + ", bounds=" + String.valueOf(this.bounds) + ", nodeCount=" + this.nodeCount;
    }
    
    static {
        ORDER = Comparator.comparingInt(o -> o.getCaveNodeType().getPriority());
    }
}
