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

package io.sentry.util;

import java.util.Iterator;
import java.util.TimeZone;
import java.util.Date;
import java.util.HashMap;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.ArrayList;
import io.sentry.vendor.gson.stream.JsonToken;
import java.util.List;
import io.sentry.JsonDeserializer;
import io.sentry.SentryLevel;
import org.jetbrains.annotations.NotNull;
import io.sentry.ILogger;
import java.util.AbstractMap;
import java.util.ArrayDeque;
import java.util.Map;
import java.util.Deque;
import io.sentry.ObjectReader;

public final class MapObjectReader implements ObjectReader
{
    private final Deque<Map.Entry<String, Object>> stack;
    
    public MapObjectReader(final Map<String, Object> root) {
        (this.stack = new ArrayDeque<Map.Entry<String, Object>>()).addLast(new AbstractMap.SimpleEntry<String, Object>(null, root));
    }
    
    @Override
    public void nextUnknown(@NotNull final ILogger logger, final Map<String, Object> unknown, final String name) {
        try {
            unknown.put(name, this.nextObjectOrNull());
        }
        catch (final Exception exception) {
            logger.log(SentryLevel.ERROR, exception, "Error deserializing unknown key: %s", name);
        }
    }
    
    @Nullable
    @Override
    public <T> List<T> nextListOrNull(@NotNull final ILogger logger, @NotNull final JsonDeserializer<T> deserializer) throws IOException {
        if (this.peek() == JsonToken.NULL) {
            this.nextNull();
            return null;
        }
        try {
            this.beginArray();
            final List<T> list = new ArrayList<T>();
            if (this.hasNext()) {
                do {
                    try {
                        list.add(deserializer.deserialize(this, logger));
                    }
                    catch (final Exception e) {
                        logger.log(SentryLevel.WARNING, "Failed to deserialize object in list.", e);
                    }
                } while (this.peek() == JsonToken.BEGIN_OBJECT);
            }
            this.endArray();
            return list;
        }
        catch (final Exception e2) {
            throw new IOException(e2);
        }
    }
    
    @Nullable
    @Override
    public <T> Map<String, T> nextMapOrNull(@NotNull final ILogger logger, @NotNull final JsonDeserializer<T> deserializer) throws IOException {
        if (this.peek() == JsonToken.NULL) {
            this.nextNull();
            return null;
        }
        try {
            this.beginObject();
            final Map<String, T> map = new HashMap<String, T>();
            if (this.hasNext()) {
                do {
                    try {
                        final String key = this.nextName();
                        map.put(key, deserializer.deserialize(this, logger));
                    }
                    catch (final Exception e) {
                        logger.log(SentryLevel.WARNING, "Failed to deserialize object in map.", e);
                    }
                } while (this.peek() == JsonToken.BEGIN_OBJECT || this.peek() == JsonToken.NAME);
            }
            this.endObject();
            return map;
        }
        catch (final Exception e2) {
            throw new IOException(e2);
        }
    }
    
    @Nullable
    @Override
    public <T> Map<String, List<T>> nextMapOfListOrNull(@NotNull final ILogger logger, @NotNull final JsonDeserializer<T> deserializer) throws IOException {
        if (this.peek() == JsonToken.NULL) {
            this.nextNull();
            return null;
        }
        final Map<String, List<T>> result = new HashMap<String, List<T>>();
        try {
            this.beginObject();
            if (this.hasNext()) {
                do {
                    final String key = this.nextName();
                    final List<T> list = this.nextListOrNull(logger, deserializer);
                    if (list != null) {
                        result.put(key, list);
                    }
                } while (this.peek() == JsonToken.BEGIN_OBJECT || this.peek() == JsonToken.NAME);
            }
            this.endObject();
            return result;
        }
        catch (final Exception e) {
            throw new IOException(e);
        }
    }
    
    @Nullable
    @Override
    public <T> T nextOrNull(@NotNull final ILogger logger, @NotNull final JsonDeserializer<T> deserializer) throws Exception {
        return (T)this.nextValueOrNull(logger, (JsonDeserializer<Object>)deserializer);
    }
    
    @Nullable
    @Override
    public Date nextDateOrNull(@NotNull final ILogger logger) throws IOException {
        final String dateString = this.nextStringOrNull();
        return ObjectReader.dateOrNull(dateString, logger);
    }
    
    @Nullable
    @Override
    public TimeZone nextTimeZoneOrNull(@NotNull final ILogger logger) throws IOException {
        final String timeZoneId = this.nextStringOrNull();
        return (timeZoneId != null) ? TimeZone.getTimeZone(timeZoneId) : null;
    }
    
    @Nullable
    @Override
    public Object nextObjectOrNull() throws IOException {
        return this.nextValueOrNull();
    }
    
    @NotNull
    @Override
    public JsonToken peek() throws IOException {
        if (this.stack.isEmpty()) {
            return JsonToken.END_DOCUMENT;
        }
        final Map.Entry<String, Object> currentEntry = this.stack.peekLast();
        if (currentEntry == null) {
            return JsonToken.END_DOCUMENT;
        }
        if (currentEntry.getKey() != null) {
            return JsonToken.NAME;
        }
        final Object value = currentEntry.getValue();
        if (value instanceof Map) {
            return JsonToken.BEGIN_OBJECT;
        }
        if (value instanceof List) {
            return JsonToken.BEGIN_ARRAY;
        }
        if (value instanceof String) {
            return JsonToken.STRING;
        }
        if (value instanceof Number) {
            return JsonToken.NUMBER;
        }
        if (value instanceof Boolean) {
            return JsonToken.BOOLEAN;
        }
        if (value instanceof JsonToken) {
            return (JsonToken)value;
        }
        return JsonToken.END_DOCUMENT;
    }
    
    @NotNull
    @Override
    public String nextName() throws IOException {
        final Map.Entry<String, Object> currentEntry = this.stack.peekLast();
        if (currentEntry != null && currentEntry.getKey() != null) {
            return currentEntry.getKey();
        }
        throw new IOException("Expected a name but was " + this.peek());
    }
    
    @Override
    public void beginObject() throws IOException {
        final Map.Entry<String, Object> currentEntry = this.stack.removeLast();
        if (currentEntry == null) {
            throw new IOException("No more entries");
        }
        final Object value = currentEntry.getValue();
        if (value instanceof Map) {
            this.stack.addLast(new AbstractMap.SimpleEntry<String, Object>(null, JsonToken.END_OBJECT));
            for (final Map.Entry<String, Object> entry : ((Map)value).entrySet()) {
                this.stack.addLast(entry);
            }
            return;
        }
        throw new IOException("Current token is not an object");
    }
    
    @Override
    public void endObject() throws IOException {
        if (this.stack.size() > 1) {
            this.stack.removeLast();
        }
    }
    
    @Override
    public void beginArray() throws IOException {
        final Map.Entry<String, Object> currentEntry = this.stack.removeLast();
        if (currentEntry == null) {
            throw new IOException("No more entries");
        }
        final Object value = currentEntry.getValue();
        if (value instanceof List) {
            this.stack.addLast(new AbstractMap.SimpleEntry<String, Object>(null, JsonToken.END_ARRAY));
            for (int i = ((List)value).size() - 1; i >= 0; --i) {
                final Object entry = ((List)value).get(i);
                this.stack.addLast(new AbstractMap.SimpleEntry<String, Object>(null, entry));
            }
            return;
        }
        throw new IOException("Current token is not an object");
    }
    
    @Override
    public void endArray() throws IOException {
        if (this.stack.size() > 1) {
            this.stack.removeLast();
        }
    }
    
    @Override
    public boolean hasNext() throws IOException {
        return !this.stack.isEmpty();
    }
    
    @Override
    public int nextInt() throws IOException {
        final Object value = this.nextValueOrNull();
        if (value instanceof Number) {
            return ((Number)value).intValue();
        }
        throw new IOException("Expected int");
    }
    
    @Nullable
    @Override
    public Integer nextIntegerOrNull() throws IOException {
        final Object value = this.nextValueOrNull();
        if (value instanceof Number) {
            return ((Number)value).intValue();
        }
        return null;
    }
    
    @Override
    public long nextLong() throws IOException {
        final Object value = this.nextValueOrNull();
        if (value instanceof Number) {
            return ((Number)value).longValue();
        }
        throw new IOException("Expected long");
    }
    
    @Nullable
    @Override
    public Long nextLongOrNull() throws IOException {
        final Object value = this.nextValueOrNull();
        if (value instanceof Number) {
            return ((Number)value).longValue();
        }
        return null;
    }
    
    @Override
    public String nextString() throws IOException {
        final String value = this.nextValueOrNull();
        if (value != null) {
            return value;
        }
        throw new IOException("Expected string");
    }
    
    @Nullable
    @Override
    public String nextStringOrNull() throws IOException {
        return this.nextValueOrNull();
    }
    
    @Override
    public boolean nextBoolean() throws IOException {
        final Boolean value = this.nextValueOrNull();
        if (value != null) {
            return value;
        }
        throw new IOException("Expected boolean");
    }
    
    @Nullable
    @Override
    public Boolean nextBooleanOrNull() throws IOException {
        return this.nextValueOrNull();
    }
    
    @Override
    public double nextDouble() throws IOException {
        final Object value = this.nextValueOrNull();
        if (value instanceof Number) {
            return ((Number)value).doubleValue();
        }
        throw new IOException("Expected double");
    }
    
    @Nullable
    @Override
    public Double nextDoubleOrNull() throws IOException {
        final Object value = this.nextValueOrNull();
        if (value instanceof Number) {
            return ((Number)value).doubleValue();
        }
        return null;
    }
    
    @Nullable
    @Override
    public Float nextFloatOrNull() throws IOException {
        final Object value = this.nextValueOrNull();
        if (value instanceof Number) {
            return ((Number)value).floatValue();
        }
        return null;
    }
    
    @Override
    public float nextFloat() throws IOException {
        final Object value = this.nextValueOrNull();
        if (value instanceof Number) {
            return ((Number)value).floatValue();
        }
        throw new IOException("Expected float");
    }
    
    @Override
    public void nextNull() throws IOException {
        final Object value = this.nextValueOrNull();
        if (value != null) {
            throw new IOException("Expected null but was " + this.peek());
        }
    }
    
    @Override
    public void setLenient(final boolean lenient) {
    }
    
    @Override
    public void skipValue() throws IOException {
    }
    
    @Nullable
    private <T> T nextValueOrNull() throws IOException {
        try {
            return this.nextValueOrNull(null, (JsonDeserializer<T>)null);
        }
        catch (final Exception e) {
            throw new IOException(e);
        }
    }
    
    @Nullable
    private <T> T nextValueOrNull(@Nullable final ILogger logger, @Nullable final JsonDeserializer<T> deserializer) throws Exception {
        final Map.Entry<String, Object> currentEntry = this.stack.peekLast();
        if (currentEntry == null) {
            return null;
        }
        final T value = (T)currentEntry.getValue();
        if (deserializer != null && logger != null) {
            return deserializer.deserialize(this, logger);
        }
        this.stack.removeLast();
        return value;
    }
    
    @Override
    public void close() throws IOException {
        this.stack.clear();
    }
}
