package com.google.gson;

import com.google.gson.internal.$Gson$Preconditions;
import com.google.gson.internal.Streams;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;

final class TreeTypeAdapter<T> extends TypeAdapter<T> {
   private final JsonSerializer<T> serializer;
   private final JsonDeserializer<T> deserializer;
   private final Gson gson;
   private final TypeToken<T> typeToken;
   private final TypeAdapterFactory skipPast;
   private TypeAdapter<T> delegate;

   private TreeTypeAdapter(JsonSerializer<T> serializer, JsonDeserializer<T> deserializer, Gson gson, TypeToken<T> typeToken, TypeAdapterFactory skipPast) {
      this.serializer = serializer;
      this.deserializer = deserializer;
      this.gson = gson;
      this.typeToken = typeToken;
      this.skipPast = skipPast;
   }

   public T read(JsonReader in) throws IOException {
      if (this.deserializer == null) {
         return this.delegate().read(in);
      } else {
         JsonElement value = Streams.parse(in);
         return value.isJsonNull() ? null : this.deserializer.deserialize(value, this.typeToken.getType(), this.gson.deserializationContext);
      }
   }

   public void write(JsonWriter out, T value) throws IOException {
      if (this.serializer == null) {
         this.delegate().write(out, value);
      } else if (value == null) {
         out.nullValue();
      } else {
         JsonElement tree = this.serializer.serialize(value, this.typeToken.getType(), this.gson.serializationContext);
         Streams.write(tree, out);
      }
   }

   private TypeAdapter<T> delegate() {
      TypeAdapter<T> d = this.delegate;
      return d != null ? d : (this.delegate = this.gson.getDelegateAdapter(this.skipPast, this.typeToken));
   }

   public static TypeAdapterFactory newFactory(TypeToken<?> exactType, Object typeAdapter) {
      return new TreeTypeAdapter.SingleTypeFactory(typeAdapter, exactType, false, (Class)null);
   }

   public static TypeAdapterFactory newFactoryWithMatchRawType(TypeToken<?> exactType, Object typeAdapter) {
      boolean matchRawType = exactType.getType() == exactType.getRawType();
      return new TreeTypeAdapter.SingleTypeFactory(typeAdapter, exactType, matchRawType, (Class)null);
   }

   public static TypeAdapterFactory newTypeHierarchyFactory(Class<?> hierarchyType, Object typeAdapter) {
      return new TreeTypeAdapter.SingleTypeFactory(typeAdapter, (TypeToken)null, false, hierarchyType);
   }

   // $FF: synthetic method
   TreeTypeAdapter(JsonSerializer x0, JsonDeserializer x1, Gson x2, TypeToken x3, TypeAdapterFactory x4, Object x5) {
      this(x0, x1, x2, x3, x4);
   }

   private static class SingleTypeFactory implements TypeAdapterFactory {
      private final TypeToken<?> exactType;
      private final boolean matchRawType;
      private final Class<?> hierarchyType;
      private final JsonSerializer<?> serializer;
      private final JsonDeserializer<?> deserializer;

      private SingleTypeFactory(Object typeAdapter, TypeToken<?> exactType, boolean matchRawType, Class<?> hierarchyType) {
         this.serializer = typeAdapter instanceof JsonSerializer ? (JsonSerializer)typeAdapter : null;
         this.deserializer = typeAdapter instanceof JsonDeserializer ? (JsonDeserializer)typeAdapter : null;
         $Gson$Preconditions.checkArgument(this.serializer != null || this.deserializer != null);
         this.exactType = exactType;
         this.matchRawType = matchRawType;
         this.hierarchyType = hierarchyType;
      }

      public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
         boolean matches = this.exactType != null ? this.exactType.equals(type) || this.matchRawType && this.exactType.getType() == type.getRawType() : this.hierarchyType.isAssignableFrom(type.getRawType());
         return matches ? new TreeTypeAdapter(this.serializer, this.deserializer, gson, type, this) : null;
      }

      // $FF: synthetic method
      SingleTypeFactory(Object x0, TypeToken x1, boolean x2, Class x3, Object x4) {
         this(x0, x1, x2, x3);
      }
   }
}
