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

package com.google.gson.internal.bind;

import java.util.Objects;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonSerializer;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;
import com.google.gson.Gson;
import com.google.gson.annotations.JsonAdapter;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.google.gson.internal.ConstructorConstructor;
import com.google.gson.TypeAdapterFactory;

public final class JsonAdapterAnnotationTypeAdapterFactory implements TypeAdapterFactory
{
    private static final TypeAdapterFactory TREE_TYPE_CLASS_DUMMY_FACTORY;
    private static final TypeAdapterFactory TREE_TYPE_FIELD_DUMMY_FACTORY;
    private final ConstructorConstructor constructorConstructor;
    private final ConcurrentMap<Class<?>, TypeAdapterFactory> adapterFactoryMap;
    
    public JsonAdapterAnnotationTypeAdapterFactory(final ConstructorConstructor constructorConstructor) {
        this.constructorConstructor = constructorConstructor;
        this.adapterFactoryMap = new ConcurrentHashMap<Class<?>, TypeAdapterFactory>();
    }
    
    private static JsonAdapter getAnnotation(final Class<?> rawType) {
        return rawType.getAnnotation(JsonAdapter.class);
    }
    
    @Override
    public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> targetType) {
        final Class<? super T> rawType = targetType.getRawType();
        final JsonAdapter annotation = getAnnotation(rawType);
        if (annotation == null) {
            return null;
        }
        return (TypeAdapter<T>)this.getTypeAdapter(this.constructorConstructor, gson, targetType, annotation, true);
    }
    
    private static Object createAdapter(final ConstructorConstructor constructorConstructor, final Class<?> adapterClass) {
        final boolean allowUnsafe = true;
        return constructorConstructor.get((TypeToken<Object>)TypeToken.get(adapterClass), allowUnsafe).construct();
    }
    
    private TypeAdapterFactory putFactoryAndGetCurrent(final Class<?> rawType, final TypeAdapterFactory factory) {
        final TypeAdapterFactory existingFactory = this.adapterFactoryMap.putIfAbsent(rawType, factory);
        return (existingFactory != null) ? existingFactory : factory;
    }
    
    TypeAdapter<?> getTypeAdapter(final ConstructorConstructor constructorConstructor, final Gson gson, final TypeToken<?> type, final JsonAdapter annotation, final boolean isClassAnnotation) {
        final Object instance = createAdapter(constructorConstructor, annotation.value());
        boolean nullSafe = annotation.nullSafe();
        TypeAdapter<?> typeAdapter;
        if (instance instanceof TypeAdapter) {
            typeAdapter = (TypeAdapter)instance;
        }
        else if (instance instanceof TypeAdapterFactory) {
            TypeAdapterFactory factory = (TypeAdapterFactory)instance;
            if (isClassAnnotation) {
                factory = this.putFactoryAndGetCurrent(type.getRawType(), factory);
            }
            typeAdapter = factory.create(gson, type);
        }
        else {
            if (!(instance instanceof JsonSerializer) && !(instance instanceof JsonDeserializer)) {
                throw new IllegalArgumentException("Invalid attempt to bind an instance of " + instance.getClass().getName() + " as a @JsonAdapter for " + type.toString() + ". @JsonAdapter value must be a TypeAdapter, TypeAdapterFactory, JsonSerializer or JsonDeserializer.");
            }
            final JsonSerializer<?> serializer = (instance instanceof JsonSerializer) ? ((JsonSerializer)instance) : null;
            final JsonDeserializer<?> deserializer = (instance instanceof JsonDeserializer) ? ((JsonDeserializer)instance) : null;
            TypeAdapterFactory skipPast;
            if (isClassAnnotation) {
                skipPast = JsonAdapterAnnotationTypeAdapterFactory.TREE_TYPE_CLASS_DUMMY_FACTORY;
            }
            else {
                skipPast = JsonAdapterAnnotationTypeAdapterFactory.TREE_TYPE_FIELD_DUMMY_FACTORY;
            }
            final TypeAdapter<?> tempAdapter = typeAdapter = new TreeTypeAdapter<Object>(serializer, deserializer, gson, type, skipPast, nullSafe);
            nullSafe = false;
        }
        if (typeAdapter != null && nullSafe) {
            typeAdapter = typeAdapter.nullSafe();
        }
        return typeAdapter;
    }
    
    public boolean isClassJsonAdapterFactory(final TypeToken<?> type, final TypeAdapterFactory factory) {
        Objects.requireNonNull(type);
        Objects.requireNonNull(factory);
        if (factory == JsonAdapterAnnotationTypeAdapterFactory.TREE_TYPE_CLASS_DUMMY_FACTORY) {
            return true;
        }
        final Class<?> rawType = type.getRawType();
        final TypeAdapterFactory existingFactory = this.adapterFactoryMap.get(rawType);
        if (existingFactory != null) {
            return existingFactory == factory;
        }
        final JsonAdapter annotation = getAnnotation(rawType);
        if (annotation == null) {
            return false;
        }
        final Class<?> adapterClass = annotation.value();
        if (!TypeAdapterFactory.class.isAssignableFrom(adapterClass)) {
            return false;
        }
        final Object adapter = createAdapter(this.constructorConstructor, adapterClass);
        final TypeAdapterFactory newFactory = (TypeAdapterFactory)adapter;
        return this.putFactoryAndGetCurrent(rawType, newFactory) == factory;
    }
    
    static {
        TREE_TYPE_CLASS_DUMMY_FACTORY = new DummyTypeAdapterFactory();
        TREE_TYPE_FIELD_DUMMY_FACTORY = new DummyTypeAdapterFactory();
    }
    
    private static class DummyTypeAdapterFactory implements TypeAdapterFactory
    {
        @Override
        public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> type) {
            throw new AssertionError((Object)"Factory should not be used");
        }
    }
}
