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

package com.google.gson.internal.bind;

import java.util.Iterator;
import java.util.Map;
import com.google.gson.stream.JsonWriter;
import java.util.Deque;
import java.util.ArrayDeque;
import com.google.gson.JsonNull;
import com.google.gson.internal.LazilyParsedNumber;
import com.google.gson.JsonPrimitive;
import java.io.IOException;
import com.google.gson.JsonObject;
import com.google.gson.JsonArray;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.JsonElement;
import com.google.gson.TypeAdapter;

class JsonElementTypeAdapter extends TypeAdapter<JsonElement>
{
    static final JsonElementTypeAdapter ADAPTER;
    
    private JsonElementTypeAdapter() {
    }
    
    private JsonElement tryBeginNesting(final JsonReader in, final JsonToken peeked) throws IOException {
        switch (peeked) {
            case BEGIN_ARRAY: {
                in.beginArray();
                return new JsonArray();
            }
            case BEGIN_OBJECT: {
                in.beginObject();
                return new JsonObject();
            }
            default: {
                return null;
            }
        }
    }
    
    private JsonElement readTerminal(final JsonReader in, final JsonToken peeked) throws IOException {
        switch (peeked) {
            case STRING: {
                return new JsonPrimitive(in.nextString());
            }
            case NUMBER: {
                final String number = in.nextString();
                return new JsonPrimitive(new LazilyParsedNumber(number));
            }
            case BOOLEAN: {
                return new JsonPrimitive(in.nextBoolean());
            }
            case NULL: {
                in.nextNull();
                return JsonNull.INSTANCE;
            }
            default: {
                throw new IllegalStateException("Unexpected token: " + peeked);
            }
        }
    }
    
    @Override
    public JsonElement read(final JsonReader in) throws IOException {
        if (in instanceof JsonTreeReader) {
            return ((JsonTreeReader)in).nextJsonElement();
        }
        JsonToken peeked = in.peek();
        JsonElement current = this.tryBeginNesting(in, peeked);
        if (current == null) {
            return this.readTerminal(in, peeked);
        }
        final Deque<JsonElement> stack = new ArrayDeque<JsonElement>();
        while (true) {
            if (in.hasNext()) {
                String name = null;
                if (current instanceof JsonObject) {
                    name = in.nextName();
                }
                peeked = in.peek();
                JsonElement value = this.tryBeginNesting(in, peeked);
                final boolean isNesting = value != null;
                if (value == null) {
                    value = this.readTerminal(in, peeked);
                }
                if (current instanceof JsonArray) {
                    ((JsonArray)current).add(value);
                }
                else {
                    ((JsonObject)current).add(name, value);
                }
                if (!isNesting) {
                    continue;
                }
                stack.addLast(current);
                current = value;
            }
            else {
                if (current instanceof JsonArray) {
                    in.endArray();
                }
                else {
                    in.endObject();
                }
                if (stack.isEmpty()) {
                    break;
                }
                current = stack.removeLast();
            }
        }
        return current;
    }
    
    @Override
    public void write(final JsonWriter out, final JsonElement value) throws IOException {
        if (value == null || value.isJsonNull()) {
            out.nullValue();
        }
        else if (value.isJsonPrimitive()) {
            final JsonPrimitive primitive = value.getAsJsonPrimitive();
            if (primitive.isNumber()) {
                out.value(primitive.getAsNumber());
            }
            else if (primitive.isBoolean()) {
                out.value(primitive.getAsBoolean());
            }
            else {
                out.value(primitive.getAsString());
            }
        }
        else if (value.isJsonArray()) {
            out.beginArray();
            for (final JsonElement e : value.getAsJsonArray()) {
                this.write(out, e);
            }
            out.endArray();
        }
        else {
            if (!value.isJsonObject()) {
                throw new IllegalArgumentException("Couldn't write " + value.getClass());
            }
            out.beginObject();
            for (final Map.Entry<String, JsonElement> e2 : value.getAsJsonObject().entrySet()) {
                out.name(e2.getKey());
                this.write(out, e2.getValue());
            }
            out.endObject();
        }
    }
    
    static {
        ADAPTER = new JsonElementTypeAdapter();
    }
}
