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

package com.hypixel.hytale.codec;

import java.util.function.Supplier;
import java.io.IOException;
import com.hypixel.hytale.codec.util.RawJsonReader;
import java.util.Arrays;
import java.util.function.Function;
import com.hypixel.hytale.codec.validation.ThrowingValidationResults;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import com.hypixel.hytale.logger.util.GithubMessageUtil;
import java.util.Map;
import com.hypixel.hytale.codec.store.CodecStore;
import com.hypixel.hytale.codec.validation.ValidationResults;
import java.util.List;
import javax.annotation.Nonnull;

public class ExtraInfo
{
    public static final ThreadLocal<ExtraInfo> THREAD_LOCAL;
    public static final String GENERATED_ID_PREFIX = "*";
    public static final int UNSET_VERSION = Integer.MAX_VALUE;
    private final int legacyVersion;
    private final int keysInitialSize;
    @Nonnull
    private String[] stringKeys;
    @Nonnull
    private int[] intKeys;
    private int[] lineNumbers;
    private int[] columnNumbers;
    private int keysSize;
    @Nonnull
    private String[] ignoredUnknownKeys;
    private int ignoredUnknownSize;
    private final List<String> unknownKeys;
    private final ValidationResults validationResults;
    private final CodecStore codecStore;
    @Deprecated
    private final Map<String, Object> metadata;
    
    public ExtraInfo() {
        this.keysInitialSize = ((this instanceof EmptyExtraInfo) ? 0 : 128);
        this.stringKeys = new String[this.keysInitialSize];
        this.intKeys = new int[this.keysInitialSize];
        this.lineNumbers = (int[])(GithubMessageUtil.isGithub() ? new int[this.keysInitialSize] : null);
        this.columnNumbers = (int[])(GithubMessageUtil.isGithub() ? new int[this.keysInitialSize] : null);
        this.ignoredUnknownKeys = new String[this.keysInitialSize];
        this.unknownKeys = new ObjectArrayList<String>();
        this.metadata = new Object2ObjectOpenHashMap<String, Object>();
        this.legacyVersion = Integer.MAX_VALUE;
        this.validationResults = new ThrowingValidationResults(this);
        this.codecStore = CodecStore.STATIC;
    }
    
    @Deprecated
    public ExtraInfo(final int version) {
        this.keysInitialSize = ((this instanceof EmptyExtraInfo) ? 0 : 128);
        this.stringKeys = new String[this.keysInitialSize];
        this.intKeys = new int[this.keysInitialSize];
        this.lineNumbers = (int[])(GithubMessageUtil.isGithub() ? new int[this.keysInitialSize] : null);
        this.columnNumbers = (int[])(GithubMessageUtil.isGithub() ? new int[this.keysInitialSize] : null);
        this.ignoredUnknownKeys = new String[this.keysInitialSize];
        this.unknownKeys = new ObjectArrayList<String>();
        this.metadata = new Object2ObjectOpenHashMap<String, Object>();
        this.legacyVersion = version;
        this.validationResults = new ThrowingValidationResults(this);
        this.codecStore = CodecStore.STATIC;
    }
    
    @Deprecated
    public ExtraInfo(final int version, @Nonnull final Function<ExtraInfo, ValidationResults> validationResultsSupplier) {
        this.keysInitialSize = ((this instanceof EmptyExtraInfo) ? 0 : 128);
        this.stringKeys = new String[this.keysInitialSize];
        this.intKeys = new int[this.keysInitialSize];
        this.lineNumbers = (int[])(GithubMessageUtil.isGithub() ? new int[this.keysInitialSize] : null);
        this.columnNumbers = (int[])(GithubMessageUtil.isGithub() ? new int[this.keysInitialSize] : null);
        this.ignoredUnknownKeys = new String[this.keysInitialSize];
        this.unknownKeys = new ObjectArrayList<String>();
        this.metadata = new Object2ObjectOpenHashMap<String, Object>();
        this.legacyVersion = version;
        this.validationResults = validationResultsSupplier.apply(this);
        this.codecStore = CodecStore.STATIC;
    }
    
    public int getVersion() {
        return Integer.MAX_VALUE;
    }
    
    @Deprecated
    public int getLegacyVersion() {
        return this.legacyVersion;
    }
    
    public int getKeysSize() {
        return this.keysSize;
    }
    
    public CodecStore getCodecStore() {
        return this.codecStore;
    }
    
    private int nextKeyIndex() {
        final int index = this.keysSize++;
        if (this.stringKeys.length <= index) {
            final int newLength = grow(index);
            this.stringKeys = Arrays.copyOf(this.stringKeys, newLength);
            this.intKeys = Arrays.copyOf(this.intKeys, newLength);
            if (GithubMessageUtil.isGithub()) {
                this.lineNumbers = Arrays.copyOf(this.lineNumbers, newLength);
                this.columnNumbers = Arrays.copyOf(this.columnNumbers, newLength);
            }
        }
        return index;
    }
    
    public void pushKey(final String key) {
        final int index = this.nextKeyIndex();
        this.stringKeys[index] = key;
    }
    
    public void pushIntKey(final int key) {
        final int index = this.nextKeyIndex();
        this.intKeys[index] = key;
    }
    
    public void pushKey(final String key, final RawJsonReader reader) {
        final int index = this.nextKeyIndex();
        this.stringKeys[index] = key;
        if (GithubMessageUtil.isGithub()) {
            this.lineNumbers[index] = reader.getLine();
            this.columnNumbers[index] = reader.getColumn();
        }
    }
    
    public void pushIntKey(final int key, final RawJsonReader reader) {
        final int index = this.nextKeyIndex();
        this.intKeys[index] = key;
        if (GithubMessageUtil.isGithub()) {
            this.lineNumbers[index] = reader.getLine();
            this.columnNumbers[index] = reader.getColumn();
        }
    }
    
    public void popKey() {
        this.stringKeys[this.keysSize] = null;
        --this.keysSize;
    }
    
    private int nextIgnoredUnknownIndex() {
        final int index = this.ignoredUnknownSize++;
        if (this.ignoredUnknownKeys.length <= index) {
            this.ignoredUnknownKeys = Arrays.copyOf(this.ignoredUnknownKeys, grow(index));
        }
        return index;
    }
    
    public void ignoreUnusedKey(final String key) {
        final int index = this.nextIgnoredUnknownIndex();
        this.ignoredUnknownKeys[index] = key;
    }
    
    public void popIgnoredUnusedKey() {
        this.ignoredUnknownKeys[this.ignoredUnknownSize] = null;
        --this.ignoredUnknownSize;
    }
    
    public boolean consumeIgnoredUnknownKey(@Nonnull final RawJsonReader reader) throws IOException {
        if (this.ignoredUnknownSize <= 0) {
            return false;
        }
        final int lastIndex = this.ignoredUnknownSize - 1;
        final String ignoredUnknownKey = this.ignoredUnknownKeys[lastIndex];
        if (ignoredUnknownKey == null) {
            return false;
        }
        if (!reader.tryConsumeString(ignoredUnknownKey)) {
            return false;
        }
        this.ignoredUnknownKeys[lastIndex] = null;
        return true;
    }
    
    public boolean consumeIgnoredUnknownKey(@Nonnull final String key) {
        if (this.ignoredUnknownSize <= 0) {
            return false;
        }
        final int lastIndex = this.ignoredUnknownSize - 1;
        if (!key.equals(this.ignoredUnknownKeys[lastIndex])) {
            return false;
        }
        this.ignoredUnknownKeys[lastIndex] = null;
        return true;
    }
    
    public void readUnknownKey(@Nonnull final RawJsonReader reader) throws IOException {
        if (this.consumeIgnoredUnknownKey(reader)) {
            return;
        }
        final String key = reader.readString();
        if (this.keysSize == 0) {
            this.unknownKeys.add(key);
        }
        else {
            this.unknownKeys.add(this.peekKey() + "." + key);
        }
    }
    
    public void addUnknownKey(@Nonnull final String key) {
        switch (key) {
            case "$Title":
            case "$Comment":
            case "$TODO":
            case "$Author":
            case "$Position":
            case "$FloatingFunctionNodes":
            case "$Groups":
            case "$WorkspaceID":
            case "$NodeEditorMetadata":
            case "$NodeId": {
                return;
            }
            default: {
                if (this.consumeIgnoredUnknownKey(key)) {
                    return;
                }
                if (this.keysSize == 0) {
                    if ("Parent".equals(key)) {
                        return;
                    }
                    this.unknownKeys.add(key);
                }
                else {
                    this.unknownKeys.add(this.peekKey() + "." + key);
                }
            }
        }
    }
    
    public String peekKey() {
        return this.peekKey('.');
    }
    
    public String peekKey(final char separator) {
        if (this.keysSize == 0) {
            return "";
        }
        if (this.keysSize != 1) {
            final StringBuilder sb = new StringBuilder();
            for (int i = 0; i < this.keysSize; ++i) {
                if (i > 0) {
                    sb.append(separator);
                }
                final String str = this.stringKeys[i];
                if (str != null) {
                    sb.append(str);
                }
                else {
                    sb.append(this.intKeys[i]);
                }
            }
            return sb.toString();
        }
        final String str2 = this.stringKeys[0];
        if (str2 != null) {
            return str2;
        }
        return String.valueOf(this.intKeys[0]);
    }
    
    public int peekLine() {
        if (GithubMessageUtil.isGithub() && this.keysSize > 0) {
            return this.lineNumbers[this.keysSize - 1];
        }
        return -1;
    }
    
    public int peekColumn() {
        if (GithubMessageUtil.isGithub() && this.keysSize > 0) {
            return this.columnNumbers[this.keysSize - 1];
        }
        return -1;
    }
    
    public List<String> getUnknownKeys() {
        return this.unknownKeys;
    }
    
    public ValidationResults getValidationResults() {
        return this.validationResults;
    }
    
    @Deprecated
    public Map<String, Object> getMetadata() {
        return this.metadata;
    }
    
    public void appendDetailsTo(@Nonnull final StringBuilder sb) {
        sb.append("ExtraInfo\n");
    }
    
    @Nonnull
    @Override
    public String toString() {
        return "ExtraInfo{version=" + this.legacyVersion + ", stringKeys=" + Arrays.toString(this.stringKeys) + ", intKeys=" + Arrays.toString(this.intKeys) + ", keysSize=" + this.keysSize + ", ignoredUnknownKeys=" + Arrays.toString(this.ignoredUnknownKeys) + ", ignoredUnknownSize=" + this.ignoredUnknownSize + ", unknownKeys=" + String.valueOf(this.unknownKeys) + ", validationResults=" + String.valueOf(this.validationResults);
    }
    
    private static int grow(final int oldSize) {
        return oldSize + (oldSize >> 1);
    }
    
    static {
        THREAD_LOCAL = ThreadLocal.withInitial((Supplier<? extends ExtraInfo>)ExtraInfo::new);
    }
}
