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

package io.sentry;

import java.util.HashMap;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import org.jetbrains.annotations.ApiStatus;

@ApiStatus.Internal
public final class JsonObjectDeserializer
{
    private final ArrayList<Token> tokens;
    
    public JsonObjectDeserializer() {
        this.tokens = new ArrayList<Token>();
    }
    
    @Nullable
    public Object deserialize(@NotNull final JsonObjectReader reader) throws IOException {
        this.parse(reader);
        final Token root = this.getCurrentToken();
        if (root != null) {
            return root.getValue();
        }
        return null;
    }
    
    private void parse(@NotNull final JsonObjectReader reader) throws IOException {
        boolean done = false;
        switch (reader.peek()) {
            case BEGIN_ARRAY: {
                reader.beginArray();
                this.pushCurrentToken(new TokenArray());
                break;
            }
            case END_ARRAY: {
                reader.endArray();
                done = this.handleArrayOrMapEnd();
                break;
            }
            case BEGIN_OBJECT: {
                reader.beginObject();
                this.pushCurrentToken(new TokenMap());
                break;
            }
            case END_OBJECT: {
                reader.endObject();
                done = this.handleArrayOrMapEnd();
                break;
            }
            case NAME: {
                this.pushCurrentToken(new TokenName(reader.nextName()));
                break;
            }
            case STRING: {
                done = this.handlePrimitive(() -> reader.nextString());
                break;
            }
            case NUMBER: {
                done = this.handlePrimitive(() -> this.nextNumber(reader));
                break;
            }
            case BOOLEAN: {
                done = this.handlePrimitive(() -> reader.nextBoolean());
                break;
            }
            case NULL: {
                reader.nextNull();
                done = this.handlePrimitive(() -> null);
                break;
            }
            case END_DOCUMENT: {
                done = true;
                break;
            }
        }
        if (!done) {
            this.parse(reader);
        }
    }
    
    private boolean handleArrayOrMapEnd() {
        if (this.hasOneToken()) {
            return true;
        }
        final Token arrayOrMapToken = this.getCurrentToken();
        this.popCurrentToken();
        if (this.getCurrentToken() instanceof TokenName) {
            final TokenName tokenName = (TokenName)this.getCurrentToken();
            this.popCurrentToken();
            final TokenMap tokenMap = (TokenMap)this.getCurrentToken();
            if (tokenName != null && arrayOrMapToken != null && tokenMap != null) {
                tokenMap.value.put(tokenName.value, arrayOrMapToken.getValue());
            }
        }
        else if (this.getCurrentToken() instanceof TokenArray) {
            final TokenArray tokenArray = (TokenArray)this.getCurrentToken();
            if (arrayOrMapToken != null && tokenArray != null) {
                tokenArray.value.add(arrayOrMapToken.getValue());
            }
        }
        return false;
    }
    
    private boolean handlePrimitive(final NextValue callback) throws IOException {
        final Object primitive = callback.nextValue();
        if (this.getCurrentToken() == null && primitive != null) {
            this.pushCurrentToken(new TokenPrimitive(primitive));
            return true;
        }
        if (this.getCurrentToken() instanceof TokenName) {
            final TokenName tokenNameNumber = (TokenName)this.getCurrentToken();
            this.popCurrentToken();
            final TokenMap tokenMapNumber = (TokenMap)this.getCurrentToken();
            tokenMapNumber.value.put(tokenNameNumber.value, primitive);
        }
        else if (this.getCurrentToken() instanceof TokenArray) {
            final TokenArray tokenArrayNumber = (TokenArray)this.getCurrentToken();
            tokenArrayNumber.value.add(primitive);
        }
        return false;
    }
    
    private Object nextNumber(final JsonObjectReader reader) throws IOException {
        try {
            return reader.nextInt();
        }
        catch (final Exception ex) {
            try {
                return reader.nextDouble();
            }
            catch (final Exception ex2) {
                return reader.nextLong();
            }
        }
    }
    
    @Nullable
    private Token getCurrentToken() {
        if (this.tokens.isEmpty()) {
            return null;
        }
        return this.tokens.get(this.tokens.size() - 1);
    }
    
    private void pushCurrentToken(final Token token) {
        this.tokens.add(token);
    }
    
    private void popCurrentToken() {
        if (this.tokens.isEmpty()) {
            return;
        }
        this.tokens.remove(this.tokens.size() - 1);
    }
    
    private boolean hasOneToken() {
        return this.tokens.size() == 1;
    }
    
    private static final class TokenName implements Token
    {
        final String value;
        
        TokenName(@NotNull final String value) {
            this.value = value;
        }
        
        @NotNull
        @Override
        public Object getValue() {
            return this.value;
        }
    }
    
    private static final class TokenPrimitive implements Token
    {
        final Object value;
        
        TokenPrimitive(@NotNull final Object value) {
            this.value = value;
        }
        
        @NotNull
        @Override
        public Object getValue() {
            return this.value;
        }
    }
    
    private static final class TokenArray implements Token
    {
        final ArrayList<Object> value;
        
        private TokenArray() {
            this.value = new ArrayList<Object>();
        }
        
        @NotNull
        @Override
        public Object getValue() {
            return this.value;
        }
    }
    
    private static final class TokenMap implements Token
    {
        final HashMap<String, Object> value;
        
        private TokenMap() {
            this.value = new HashMap<String, Object>();
        }
        
        @NotNull
        @Override
        public Object getValue() {
            return this.value;
        }
    }
    
    private interface Token
    {
        @NotNull
        Object getValue();
    }
    
    private interface NextValue
    {
        @Nullable
        Object nextValue() throws IOException;
    }
}
