package net.minecraft.world.level.storage.loot;

import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonParseException;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.GsonHelper;
import com.google.gson.JsonDeserializationContext;
import java.lang.reflect.Type;
import com.google.gson.JsonElement;
import com.google.gson.JsonSerializer;
import com.google.gson.JsonDeserializer;
import javax.annotation.Nullable;
import com.mojang.datafixers.util.Pair;
import java.util.function.Function;
import net.minecraft.core.Registry;

public class GsonAdapterFactory {
    public static <E, T extends SerializerType<E>> Builder<E, T> builder(final Registry<T> gl, final String string2, final String string3, final Function<E, T> function) {
        return new Builder<E, T>((Registry)gl, string2, string3, (Function)function);
    }
    
    public static class Builder<E, T extends SerializerType<E>> {
        private final Registry<T> registry;
        private final String elementName;
        private final String typeKey;
        private final Function<E, T> typeGetter;
        @Nullable
        private Pair<T, DefaultSerializer<? extends E>> defaultType;
        
        private Builder(final Registry<T> gl, final String string2, final String string3, final Function<E, T> function) {
            this.registry = gl;
            this.elementName = string2;
            this.typeKey = string3;
            this.typeGetter = function;
        }
        
        public Object build() {
            return new JsonAdapter((Registry)this.registry, this.elementName, this.typeKey, (Function)this.typeGetter, (Pair)this.defaultType);
        }
    }
    
    static class JsonAdapter<E, T extends SerializerType<E>> implements JsonDeserializer<E>, JsonSerializer<E> {
        private final Registry<T> registry;
        private final String elementName;
        private final String typeKey;
        private final Function<E, T> typeGetter;
        @Nullable
        private final Pair<T, DefaultSerializer<? extends E>> defaultType;
        
        private JsonAdapter(final Registry<T> gl, final String string2, final String string3, final Function<E, T> function, @Nullable final Pair<T, DefaultSerializer<? extends E>> pair) {
            this.registry = gl;
            this.elementName = string2;
            this.typeKey = string3;
            this.typeGetter = function;
            this.defaultType = pair;
        }
        
        @Override
        public E deserialize(final JsonElement jsonElement, final Type type, final JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
            if (jsonElement.isJsonObject()) {
                final JsonObject jsonObject5 = GsonHelper.convertToJsonObject(jsonElement, this.elementName);
                final ResourceLocation uh6 = new ResourceLocation(GsonHelper.getAsString(jsonObject5, this.typeKey));
                final T dbd7 = this.registry.get(uh6);
                if (dbd7 == null) {
                    throw new JsonSyntaxException("Unknown type '" + uh6 + "'");
                }
                return (E)dbd7.getSerializer().deserialize(jsonObject5, jsonDeserializationContext);
            }
            else {
                if (this.defaultType == null) {
                    throw new UnsupportedOperationException("Object " + jsonElement + " can't be deserialized");
                }
                return ((DefaultSerializer)this.defaultType.getSecond()).deserialize(jsonElement, jsonDeserializationContext);
            }
        }
        
        @Override
        public JsonElement serialize(final E object, final Type type, final JsonSerializationContext jsonSerializationContext) {
            final T dbd5 = this.typeGetter.apply(object);
            if (this.defaultType != null && this.defaultType.getFirst() == dbd5) {
                return ((DefaultSerializer)this.defaultType.getSecond()).serialize(object, jsonSerializationContext);
            }
            if (dbd5 == null) {
                throw new JsonSyntaxException("Unknown type: " + object);
            }
            final JsonObject jsonObject6 = new JsonObject();
            jsonObject6.addProperty(this.typeKey, this.registry.getKey(dbd5).toString());
            dbd5.getSerializer().serialize(jsonObject6, (E)object, jsonSerializationContext);
            return jsonObject6;
        }
    }
    
    public interface DefaultSerializer<T> {
        JsonElement serialize(final T object, final JsonSerializationContext jsonSerializationContext);
        
        T deserialize(final JsonElement jsonElement, final JsonDeserializationContext jsonDeserializationContext);
    }
}
