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

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

import java.util.Iterator;
import com.hypixel.hytale.server.worldgen.loader.util.ResolvedVariantsBlockArrayLoader;
import it.unimi.dsi.fastutil.objects.ObjectIterator;
import com.hypixel.hytale.server.worldgen.util.BlockFluidEntry;
import com.hypixel.hytale.server.worldgen.util.ResolvedBlockArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonArray;
import com.hypixel.hytale.assetstore.map.BlockTypeAssetMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import com.hypixel.hytale.math.util.MathUtil;
import com.hypixel.hytale.server.worldgen.loader.util.ResolvedBlockArrayJsonLoader;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
import it.unimi.dsi.fastutil.longs.Long2ObjectMaps;
import com.google.gson.JsonElement;
import java.nio.file.Path;
import javax.annotation.Nonnull;
import com.hypixel.hytale.procedurallib.json.SeedString;
import com.hypixel.hytale.server.worldgen.util.condition.BlockMaskCondition;
import com.hypixel.hytale.server.worldgen.SeedStringResource;
import com.hypixel.hytale.procedurallib.json.JsonLoader;

public class BlockPlacementMaskJsonLoader extends JsonLoader<SeedStringResource, BlockMaskCondition>
{
    private String fileName;
    
    public BlockPlacementMaskJsonLoader(@Nonnull final SeedString<SeedStringResource> seed, final Path dataFolder, final JsonElement json) {
        super(seed.append(".BlockMaskCondition"), dataFolder, json);
    }
    
    @Override
    public BlockMaskCondition load() {
        final BlockPlacementMaskRegistry registry = ((SeedStringResource)this.seed.get()).getBlockMaskRegistry();
        if (this.fileName != null) {
            final BlockMaskCondition mask = registry.getIfPresentFileMask(this.fileName);
            if (mask != null) {
                return mask;
            }
        }
        Long2ObjectMap<BlockMaskCondition.Mask> specificMasks = Long2ObjectMaps.emptyMap();
        BlockMaskCondition.Mask defaultMask;
        if (this.json == null || this.json.isJsonNull()) {
            defaultMask = BlockMaskCondition.DEFAULT_MASK;
        }
        else {
            if (this.has("Default")) {
                defaultMask = new BlockMaskCondition.Mask(this.loadEntries(this.get("Default").getAsJsonArray()));
            }
            else {
                defaultMask = BlockMaskCondition.DEFAULT_MASK;
            }
            if (this.has("Specific")) {
                final BlockTypeAssetMap<String, BlockType> assetMap = BlockType.getAssetMap();
                specificMasks = new Long2ObjectOpenHashMap<BlockMaskCondition.Mask>();
                final JsonArray array = this.get("Specific").getAsJsonArray();
                for (int i = 0; i < array.size(); ++i) {
                    try {
                        final JsonObject specificObject = array.get(i).getAsJsonObject();
                        final JsonElement blocksElement = specificObject.get("Block");
                        final ResolvedBlockArray blocks = new ResolvedBlockArrayJsonLoader((SeedString<SeedStringResource>)this.seed, this.dataFolder, blocksElement).load();
                        for (final BlockFluidEntry blockEntry : blocks.getEntries()) {
                            final String key = assetMap.getAsset(blockEntry.blockId()).getId();
                            for (final String variant : assetMap.getSubKeys(key)) {
                                final int index = assetMap.getIndex(variant);
                                if (index == Integer.MIN_VALUE) {
                                    throw new IllegalArgumentException("Unknown key! " + variant);
                                }
                                final JsonArray rule = specificObject.getAsJsonArray("Rule");
                                specificMasks.put(MathUtil.packLong(index, blockEntry.fluidId()), new BlockMaskCondition.Mask(this.loadEntries(rule)));
                            }
                        }
                    }
                    catch (final Throwable e) {
                        throw new Error(String.format("Error while reading specific block mask #%s!", i), e);
                    }
                }
            }
        }
        final BlockMaskCondition mask2 = registry.retainOrAllocateMask(defaultMask, specificMasks);
        if (this.fileName != null) {
            registry.putFileMask(this.fileName, mask2);
        }
        return mask2;
    }
    
    @Nonnull
    protected BlockMaskCondition.MaskEntry[] loadEntries(@Nonnull final JsonArray jsonArray) {
        final BlockMaskCondition.MaskEntry[] entries = new BlockMaskCondition.MaskEntry[jsonArray.size()];
        int head = 0;
        int tail = entries.length;
        for (final JsonElement element : jsonArray) {
            if (element.isJsonObject()) {
                final JsonObject obj = element.getAsJsonObject();
                boolean replace = true;
                if (obj.has("Replace")) {
                    replace = obj.get("Replace").getAsBoolean();
                }
                final ResolvedBlockArray blocks = ResolvedVariantsBlockArrayLoader.loadSingleBlock(obj);
                entries[head++] = ((SeedStringResource)this.seed.get()).getBlockMaskRegistry().retainOrAllocateEntry(blocks, replace);
            }
            else {
                String string = element.getAsString();
                boolean replace = true;
                int beginIndex = 0;
                if (string.charAt(0) == '!') {
                    replace = false;
                    beginIndex = 1;
                }
                if (string.length() == beginIndex + 1 && string.charAt(beginIndex) == '*') {
                    if (tail < entries.length) {
                        System.arraycopy(entries, tail, entries, tail - 1, entries.length - tail);
                    }
                    entries[entries.length - 1] = (replace ? BlockMaskCondition.MaskEntry.WILDCARD_TRUE : BlockMaskCondition.MaskEntry.WILDCARD_FALSE);
                    --tail;
                }
                else {
                    string = string.substring(beginIndex);
                    final ResolvedBlockArray blocks2 = ResolvedVariantsBlockArrayLoader.loadSingleBlock(string);
                    entries[head++] = ((SeedStringResource)this.seed.get()).getBlockMaskRegistry().retainOrAllocateEntry(blocks2, replace);
                }
            }
        }
        return entries;
    }
    
    @Override
    protected JsonElement loadFileConstructor(final String filePath) {
        this.fileName = filePath;
        return ((SeedStringResource)this.seed.get()).getBlockMaskRegistry().cachedFile(filePath, file -> super.loadFileConstructor(file));
    }
    
    public interface Constants
    {
        public static final String KEY_DEFAULT = "Default";
        public static final String KEY_SPECIFIC = "Specific";
        public static final String KEY_BLOCK = "Block";
        public static final String KEY_RULE = "Rule";
        public static final String ERROR_FAIL_SPECIFIC = "Error while reading specific block mask #%s!";
        public static final String ERROR_BLOCK_INVALID = "Failed to resolve block \"%s\"";
    }
}
