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

package com.hypixel.hytale.server.worldgen.loader.util;

import java.util.Collection;
import com.hypixel.hytale.server.core.asset.type.fluid.Fluid;
import com.google.gson.JsonObject;
import com.hypixel.hytale.math.util.MathUtil;
import javax.annotation.Nonnull;
import java.util.Iterator;
import java.util.List;
import com.hypixel.hytale.assetstore.map.BlockTypeAssetMap;
import com.google.gson.JsonArray;
import com.hypixel.hytale.server.worldgen.util.BlockFluidEntry;
import java.util.ArrayList;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
import com.google.gson.JsonElement;
import java.nio.file.Path;
import com.hypixel.hytale.procedurallib.json.SeedString;
import com.hypixel.hytale.server.worldgen.util.ResolvedBlockArray;
import com.hypixel.hytale.server.worldgen.SeedStringResource;
import com.hypixel.hytale.procedurallib.json.JsonLoader;

public class ResolvedVariantsBlockArrayLoader extends JsonLoader<SeedStringResource, ResolvedBlockArray>
{
    public ResolvedVariantsBlockArrayLoader(final SeedString<SeedStringResource> seed, final Path dataFolder, final JsonElement json) {
        super(seed, dataFolder, json);
    }
    
    @Nonnull
    @Override
    public ResolvedBlockArray load() {
        if (this.json == null || this.json.isJsonNull()) {
            return ResolvedBlockArray.EMPTY;
        }
        if (!this.json.isJsonArray()) {
            return loadSingleBlock(this.json.getAsString());
        }
        final JsonArray jsonArray = this.json.getAsJsonArray();
        if (jsonArray.size() == 1) {
            return loadSingleBlock(jsonArray.get(0).getAsString());
        }
        final BlockTypeAssetMap<String, BlockType> assetMap = BlockType.getAssetMap();
        final List<BlockFluidEntry[]> resolvedBlocksList = new ArrayList<BlockFluidEntry[]>();
        int size = 0;
        for (int k = 0; k < jsonArray.size(); ++k) {
            final String blockName = jsonArray.get(k).getAsString();
            try {
                if (assetMap.getAsset(blockName) == null) {
                    throw new IllegalArgumentException(String.valueOf(blockName));
                }
                final int index = assetMap.getIndex(blockName);
                if (index == Integer.MIN_VALUE) {
                    throw new IllegalArgumentException("Unknown key! " + blockName);
                }
                final ResolvedBlockArray cachedResolvedBlockArray = ResolvedBlockArray.RESOLVED_BLOCKS_WITH_VARIANTS.get(index);
                BlockFluidEntry[] blockVariantArray;
                if (cachedResolvedBlockArray != null) {
                    blockVariantArray = cachedResolvedBlockArray.getEntries();
                }
                else {
                    blockVariantArray = resolveBlockArrayWithVariants(blockName, assetMap, 0);
                }
                resolvedBlocksList.add(blockVariantArray);
                size += blockVariantArray.length;
            }
            catch (final IllegalArgumentException e) {
                throw new IllegalArgumentException("BlockLayer does not exist in BlockTypes", e);
            }
        }
        final BlockFluidEntry[] blocks = new BlockFluidEntry[size];
        for (final BlockFluidEntry[] array : resolvedBlocksList) {
            final BlockFluidEntry[] blockArray = array;
            for (final BlockFluidEntry block : array) {
                blocks[--size] = block;
            }
        }
        return new ResolvedBlockArray(blocks);
    }
    
    @Nonnull
    public static ResolvedBlockArray loadSingleBlock(@Nonnull final String blockName) {
        final BlockTypeAssetMap<String, BlockType> assetMap = BlockType.getAssetMap();
        try {
            if (assetMap.getAsset(blockName) == null) {
                throw new IllegalArgumentException(String.valueOf(blockName));
            }
            final int blockId = assetMap.getIndex(blockName);
            if (blockId == Integer.MIN_VALUE) {
                throw new IllegalArgumentException("Unknown block! " + blockName);
            }
            final long mapIndex = MathUtil.packLong(blockId, 0);
            final ResolvedBlockArray cachedResolvedBlockArray = ResolvedBlockArray.RESOLVED_BLOCKS_WITH_VARIANTS.get(mapIndex);
            if (cachedResolvedBlockArray != null) {
                return cachedResolvedBlockArray;
            }
            final BlockFluidEntry[] blocks = resolveBlockArrayWithVariants(blockName, assetMap, 0);
            final ResolvedBlockArray resolvedBlockArray = new ResolvedBlockArray(blocks);
            ResolvedBlockArray.RESOLVED_BLOCKS_WITH_VARIANTS.put(mapIndex, resolvedBlockArray);
            return resolvedBlockArray;
        }
        catch (final IllegalArgumentException e) {
            throw new IllegalArgumentException("BlockLayer does not exist in BlockTypes", e);
        }
    }
    
    @Nonnull
    public static ResolvedBlockArray loadSingleBlock(@Nonnull final JsonObject object) {
        final BlockTypeAssetMap<String, BlockType> assetMap = BlockType.getAssetMap();
        try {
            if (object.has("Block")) {
                final String blockName = object.get("Block").getAsString();
                if (assetMap.getAsset(blockName) == null) {
                    throw new IllegalArgumentException(String.valueOf(blockName));
                }
                final int blockId = assetMap.getIndex(blockName);
                if (blockId == Integer.MIN_VALUE) {
                    throw new IllegalArgumentException("Unknown block! " + blockName);
                }
                int fluidId = 0;
                if (object.has("Fluid")) {
                    final String fluidName = object.get("Fluid").getAsString();
                    fluidId = Fluid.getAssetMap().getIndex(fluidName);
                    if (fluidId == Integer.MIN_VALUE) {
                        throw new IllegalArgumentException("Unknown fluid! " + fluidName);
                    }
                }
                final long mapIndex = MathUtil.packLong(blockId, fluidId);
                final ResolvedBlockArray cachedResolvedBlockArray = ResolvedBlockArray.RESOLVED_BLOCKS_WITH_VARIANTS.get(mapIndex);
                if (cachedResolvedBlockArray != null) {
                    return cachedResolvedBlockArray;
                }
                final BlockFluidEntry[] blocks = resolveBlockArrayWithVariants(blockName, assetMap, fluidId);
                final ResolvedBlockArray resolvedBlockArray = new ResolvedBlockArray(blocks);
                ResolvedBlockArray.RESOLVED_BLOCKS_WITH_VARIANTS.put(mapIndex, resolvedBlockArray);
                return resolvedBlockArray;
            }
            else {
                if (object.has("Fluid")) {
                    return ResolvedBlockArrayJsonLoader.loadSingleBlock(object);
                }
                throw new IllegalArgumentException("Required either Block or Fluid key");
            }
        }
        catch (final IllegalArgumentException e) {
            throw new IllegalArgumentException("BlockLayer does not exist in BlockTypes", e);
        }
    }
    
    @Nonnull
    public static BlockFluidEntry[] resolveBlockArrayWithVariants(final String baseKey, @Nonnull final BlockTypeAssetMap<String, BlockType> assetMap, final int fluidId) {
        final List<String> variants = new ArrayList<String>(assetMap.getSubKeys(baseKey));
        final BlockFluidEntry[] blocks = new BlockFluidEntry[variants.size()];
        for (int i = 0; i < variants.size(); ++i) {
            final String key = variants.get(i);
            final int index = assetMap.getIndex(key);
            if (index == Integer.MIN_VALUE) {
                throw new IllegalArgumentException("Unknown key! " + key);
            }
            blocks[i] = new BlockFluidEntry(index, 0, fluidId);
        }
        return blocks;
    }
}
