// Generated by delombok at Tue Dec 16 19:34:53 UTC 2025
package net.md_5.bungee.serializer.dialog;

import com.google.common.base.Preconditions;
import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableBiMap;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Set;
import net.md_5.bungee.api.dialog.ConfirmationDialog;
import net.md_5.bungee.api.dialog.Dialog;
import net.md_5.bungee.api.dialog.DialogBase;
import net.md_5.bungee.api.dialog.DialogListDialog;
import net.md_5.bungee.api.dialog.MultiActionDialog;
import net.md_5.bungee.api.dialog.NoticeDialog;
import net.md_5.bungee.api.dialog.ServerLinksDialog;
import net.md_5.bungee.chat.VersionedComponentSerializer;

public class DialogSerializer implements JsonDeserializer<Dialog>, JsonSerializer<Dialog> {
    private static final ThreadLocal<Set<Dialog>> serializedDialogs = new ThreadLocal<>();
    private static final BiMap<String, Class<? extends Dialog>> TYPES;
    private final VersionedComponentSerializer serializer;

    static {
        ImmutableBiMap.Builder<String, Class<? extends Dialog>> builder = ImmutableBiMap.builder();
        builder.put("minecraft:notice", NoticeDialog.class);
        builder.put("minecraft:confirmation", ConfirmationDialog.class);
        builder.put("minecraft:multi_action", MultiActionDialog.class);
        builder.put("minecraft:server_links", ServerLinksDialog.class);
        builder.put("minecraft:dialog_list", DialogListDialog.class);
        TYPES = builder.build();
    }

    public JsonElement toJson(Dialog dialog) {
        return serializer.getGson().toJsonTree(dialog, Dialog.class);
    }

    public String toString(Dialog dialog) {
        return serializer.getGson().toJson(dialog, Dialog.class);
    }

    public Dialog deserialize(JsonElement jsonElement) {
        return serializer.getGson().fromJson(jsonElement, Dialog.class);
    }

    public Dialog deserialize(String json) {
        JsonElement jsonElement = JsonParser.parseString(json);
        return deserialize(jsonElement);
    }

    @Override
    public Dialog deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        JsonObject object = json.getAsJsonObject();
        String type = object.get("type").getAsString();
        if (object.has("base")) {
            throw new JsonParseException("Cannot explicitly specify base");
        }
        Type realType = TYPES.get(type);
        if (realType == null) {
            throw new JsonParseException("Unknown type " + type);
        }
        Dialog dialog = context.deserialize(json, realType);
        DialogBase base = context.deserialize(json, DialogBase.class);
        dialog.setBase(base);
        return dialog;
    }

    @Override
    public JsonElement serialize(Dialog src, Type typeOfSrc, JsonSerializationContext context) {
        if (src == null) {
            return JsonNull.INSTANCE;
        }
        boolean first = serializedDialogs.get() == null;
        if (first) {
            serializedDialogs.set(Collections.newSetFromMap(new IdentityHashMap<>()));
        }
        try {
            Preconditions.checkArgument(!serializedDialogs.get().contains(src), "Dialog loop");
            serializedDialogs.get().add(src);
            Class<? extends Dialog> realType = src.getClass();
            String type = TYPES.inverse().get(realType);
            Preconditions.checkArgument(type != null, "Unknown type %s", typeOfSrc);
            JsonObject object = (JsonObject) context.serialize(src, realType);
            object.addProperty("type", type);
            JsonObject base = (JsonObject) context.serialize(src.getBase());
            object.asMap().putAll(base.asMap());
            object.remove("base");
            return object;
        } finally {
            serializedDialogs.get().remove(src);
            if (first) {
                serializedDialogs.set(null);
            }
        }
    }

    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public DialogSerializer(final VersionedComponentSerializer serializer) {
        this.serializer = serializer;
    }
}
