package net.minecraft.network.chat;

import net.minecraft.Util;
import com.google.gson.TypeAdapterFactory;
import net.minecraft.util.LowerCaseEnumTypeAdapterFactory;
import com.google.gson.GsonBuilder;
import java.io.IOException;
import java.io.Reader;
import com.google.gson.stream.JsonReader;
import com.mojang.brigadier.StringReader;
import com.google.gson.JsonPrimitive;
import java.util.Map;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import net.minecraft.resources.ResourceLocation;
import com.google.gson.JsonParseException;
import net.minecraft.util.GsonHelper;
import com.google.gson.JsonDeserializationContext;
import java.lang.reflect.Type;
import com.google.gson.JsonElement;
import java.lang.reflect.Field;
import com.google.gson.Gson;
import com.google.gson.JsonSerializer;
import com.google.gson.JsonDeserializer;
import javax.annotation.Nullable;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import com.mojang.brigadier.Message;

public interface Component extends Message, FormattedText {
    Style getStyle();
    
    String getContents();
    
    default String getString() {
        return super.getString();
    }
    
    default String getString(final int integer) {
        final StringBuilder stringBuilder3 = new StringBuilder();
        final StringBuilder sb;
        final int integer2;
        this.visit(string -> {
            integer2 = integer - sb.length();
            if (integer2 <= 0) {
                return (Optional<Object>)Component.STOP_ITERATION;
            }
            else {
                sb.append((string.length() <= integer2) ? string : string.substring(0, integer2));
                return Optional.empty();
            }
        });
        return stringBuilder3.toString();
    }
    
    List<Component> getSiblings();
    
    MutableComponent plainCopy();
    
    MutableComponent copy();
    
    default <T> Optional<T> visit(final StyledContentConsumer<T> b, final Style nb) {
        final Style nb2 = this.getStyle().applyTo(nb);
        final Optional<T> optional5 = this.visitSelf((StyledContentConsumer<Object>)b, nb2);
        if (optional5.isPresent()) {
            return optional5;
        }
        for (final Component mr7 : this.getSiblings()) {
            final Optional<T> optional6 = mr7.visit((StyledContentConsumer<Object>)b, nb2);
            if (optional6.isPresent()) {
                return optional6;
            }
        }
        return Optional.<T>empty();
    }
    
    default <T> Optional<T> visit(final ContentConsumer<T> a) {
        final Optional<T> optional3 = this.visitSelf((ContentConsumer<Object>)a);
        if (optional3.isPresent()) {
            return optional3;
        }
        for (final Component mr5 : this.getSiblings()) {
            final Optional<T> optional4 = mr5.visit((ContentConsumer<Object>)a);
            if (optional4.isPresent()) {
                return optional4;
            }
        }
        return Optional.<T>empty();
    }
    
    default <T> Optional<T> visitSelf(final StyledContentConsumer<T> b, final Style nb) {
        return b.accept(nb, this.getContents());
    }
    
    default <T> Optional<T> visitSelf(final ContentConsumer<T> a) {
        return a.accept(this.getContents());
    }
    
    default Component nullToEmpty(@Nullable final String string) {
        return (string != null) ? new TextComponent(string) : TextComponent.EMPTY;
    }
    
    public static class Serializer implements JsonDeserializer<MutableComponent>, JsonSerializer<Component> {
        private static final Gson GSON;
        private static final Field JSON_READER_POS;
        private static final Field JSON_READER_LINESTART;
        
        @Override
        public MutableComponent deserialize(final JsonElement jsonElement, final Type type, final JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
            if (jsonElement.isJsonPrimitive()) {
                return new TextComponent(jsonElement.getAsString());
            }
            if (jsonElement.isJsonObject()) {
                final JsonObject jsonObject5 = jsonElement.getAsJsonObject();
                MutableComponent mx6;
                if (jsonObject5.has("text")) {
                    mx6 = new TextComponent(GsonHelper.getAsString(jsonObject5, "text"));
                }
                else if (jsonObject5.has("translate")) {
                    final String string7 = GsonHelper.getAsString(jsonObject5, "translate");
                    if (jsonObject5.has("with")) {
                        final JsonArray jsonArray8 = GsonHelper.getAsJsonArray(jsonObject5, "with");
                        final Object[] arr9 = new Object[jsonArray8.size()];
                        for (int integer10 = 0; integer10 < arr9.length; ++integer10) {
                            arr9[integer10] = this.deserialize(jsonArray8.get(integer10), type, jsonDeserializationContext);
                            if (arr9[integer10] instanceof TextComponent) {
                                final TextComponent nd11 = (TextComponent)arr9[integer10];
                                if (nd11.getStyle().isEmpty() && nd11.getSiblings().isEmpty()) {
                                    arr9[integer10] = nd11.getText();
                                }
                            }
                        }
                        mx6 = new TranslatableComponent(string7, arr9);
                    }
                    else {
                        mx6 = new TranslatableComponent(string7);
                    }
                }
                else if (jsonObject5.has("score")) {
                    final JsonObject jsonObject6 = GsonHelper.getAsJsonObject(jsonObject5, "score");
                    if (!jsonObject6.has("name") || !jsonObject6.has("objective")) {
                        throw new JsonParseException("A score component needs a least a name and an objective");
                    }
                    mx6 = new ScoreComponent(GsonHelper.getAsString(jsonObject6, "name"), GsonHelper.getAsString(jsonObject6, "objective"));
                }
                else if (jsonObject5.has("selector")) {
                    mx6 = new SelectorComponent(GsonHelper.getAsString(jsonObject5, "selector"));
                }
                else if (jsonObject5.has("keybind")) {
                    mx6 = new KeybindComponent(GsonHelper.getAsString(jsonObject5, "keybind"));
                }
                else {
                    if (!jsonObject5.has("nbt")) {
                        throw new JsonParseException("Don't know how to turn " + jsonElement + " into a Component");
                    }
                    final String string7 = GsonHelper.getAsString(jsonObject5, "nbt");
                    final boolean boolean8 = GsonHelper.getAsBoolean(jsonObject5, "interpret", false);
                    if (jsonObject5.has("block")) {
                        mx6 = new NbtComponent.BlockNbtComponent(string7, boolean8, GsonHelper.getAsString(jsonObject5, "block"));
                    }
                    else if (jsonObject5.has("entity")) {
                        mx6 = new NbtComponent.EntityNbtComponent(string7, boolean8, GsonHelper.getAsString(jsonObject5, "entity"));
                    }
                    else {
                        if (!jsonObject5.has("storage")) {
                            throw new JsonParseException("Don't know how to turn " + jsonElement + " into a Component");
                        }
                        mx6 = new NbtComponent.StorageNbtComponent(string7, boolean8, new ResourceLocation(GsonHelper.getAsString(jsonObject5, "storage")));
                    }
                }
                if (jsonObject5.has("extra")) {
                    final JsonArray jsonArray9 = GsonHelper.getAsJsonArray(jsonObject5, "extra");
                    if (jsonArray9.size() <= 0) {
                        throw new JsonParseException("Unexpected empty array of components");
                    }
                    for (int integer11 = 0; integer11 < jsonArray9.size(); ++integer11) {
                        mx6.append(this.deserialize(jsonArray9.get(integer11), type, jsonDeserializationContext));
                    }
                }
                mx6.setStyle(jsonDeserializationContext.<Style>deserialize(jsonElement, Style.class));
                return mx6;
            }
            if (jsonElement.isJsonArray()) {
                final JsonArray jsonArray10 = jsonElement.getAsJsonArray();
                MutableComponent mx6 = null;
                for (final JsonElement jsonElement2 : jsonArray10) {
                    final MutableComponent mx7 = this.deserialize(jsonElement2, (Type)jsonElement2.getClass(), jsonDeserializationContext);
                    if (mx6 == null) {
                        mx6 = mx7;
                    }
                    else {
                        mx6.append(mx7);
                    }
                }
                return mx6;
            }
            throw new JsonParseException("Don't know how to turn " + jsonElement + " into a Component");
        }
        
        private void serializeStyle(final Style nb, final JsonObject jsonObject, final JsonSerializationContext jsonSerializationContext) {
            final JsonElement jsonElement5 = jsonSerializationContext.serialize(nb);
            if (jsonElement5.isJsonObject()) {
                final JsonObject jsonObject2 = (JsonObject)jsonElement5;
                for (final Map.Entry<String, JsonElement> entry8 : jsonObject2.entrySet()) {
                    jsonObject.add(entry8.getKey(), entry8.getValue());
                }
            }
        }
        
        @Override
        public JsonElement serialize(final Component mr, final Type type, final JsonSerializationContext jsonSerializationContext) {
            final JsonObject jsonObject5 = new JsonObject();
            if (!mr.getStyle().isEmpty()) {
                this.serializeStyle(mr.getStyle(), jsonObject5, jsonSerializationContext);
            }
            if (!mr.getSiblings().isEmpty()) {
                final JsonArray jsonArray6 = new JsonArray();
                for (final Component mr2 : mr.getSiblings()) {
                    jsonArray6.add(this.serialize(mr2, mr2.getClass(), jsonSerializationContext));
                }
                jsonObject5.add("extra", jsonArray6);
            }
            if (mr instanceof TextComponent) {
                jsonObject5.addProperty("text", ((TextComponent)mr).getText());
            }
            else if (mr instanceof TranslatableComponent) {
                final TranslatableComponent ne6 = (TranslatableComponent)mr;
                jsonObject5.addProperty("translate", ne6.getKey());
                if (ne6.getArgs() != null && ne6.getArgs().length > 0) {
                    final JsonArray jsonArray7 = new JsonArray();
                    for (final Object object11 : ne6.getArgs()) {
                        if (object11 instanceof Component) {
                            jsonArray7.add(this.serialize((Component)object11, object11.getClass(), jsonSerializationContext));
                        }
                        else {
                            jsonArray7.add(new JsonPrimitive(String.valueOf(object11)));
                        }
                    }
                    jsonObject5.add("with", jsonArray7);
                }
            }
            else if (mr instanceof ScoreComponent) {
                final ScoreComponent mz6 = (ScoreComponent)mr;
                final JsonObject jsonObject6 = new JsonObject();
                jsonObject6.addProperty("name", mz6.getName());
                jsonObject6.addProperty("objective", mz6.getObjective());
                jsonObject5.add("score", jsonObject6);
            }
            else if (mr instanceof SelectorComponent) {
                final SelectorComponent na6 = (SelectorComponent)mr;
                jsonObject5.addProperty("selector", na6.getPattern());
            }
            else if (mr instanceof KeybindComponent) {
                final KeybindComponent mw6 = (KeybindComponent)mr;
                jsonObject5.addProperty("keybind", mw6.getName());
            }
            else {
                if (!(mr instanceof NbtComponent)) {
                    throw new IllegalArgumentException("Don't know how to serialize " + mr + " as a Component");
                }
                final NbtComponent my6 = (NbtComponent)mr;
                jsonObject5.addProperty("nbt", my6.getNbtPath());
                jsonObject5.addProperty("interpret", my6.isInterpreting());
                if (mr instanceof NbtComponent.BlockNbtComponent) {
                    final NbtComponent.BlockNbtComponent a7 = (NbtComponent.BlockNbtComponent)mr;
                    jsonObject5.addProperty("block", a7.getPos());
                }
                else if (mr instanceof NbtComponent.EntityNbtComponent) {
                    final NbtComponent.EntityNbtComponent b7 = (NbtComponent.EntityNbtComponent)mr;
                    jsonObject5.addProperty("entity", b7.getSelector());
                }
                else {
                    if (!(mr instanceof NbtComponent.StorageNbtComponent)) {
                        throw new IllegalArgumentException("Don't know how to serialize " + mr + " as a Component");
                    }
                    final NbtComponent.StorageNbtComponent c7 = (NbtComponent.StorageNbtComponent)mr;
                    jsonObject5.addProperty("storage", c7.getId().toString());
                }
            }
            return jsonObject5;
        }
        
        public static String toJson(final Component mr) {
            return Serializer.GSON.toJson(mr);
        }
        
        public static JsonElement toJsonTree(final Component mr) {
            return Serializer.GSON.toJsonTree(mr);
        }
        
        @Nullable
        public static MutableComponent fromJson(final String string) {
            return GsonHelper.<MutableComponent>fromJson(Serializer.GSON, string, MutableComponent.class, false);
        }
        
        @Nullable
        public static MutableComponent fromJson(final JsonElement jsonElement) {
            return Serializer.GSON.<MutableComponent>fromJson(jsonElement, MutableComponent.class);
        }
        
        @Nullable
        public static MutableComponent fromJsonLenient(final String string) {
            return GsonHelper.<MutableComponent>fromJson(Serializer.GSON, string, MutableComponent.class, true);
        }
        
        public static MutableComponent fromJson(final StringReader stringReader) {
            try {
                final JsonReader jsonReader2 = new JsonReader(new java.io.StringReader(stringReader.getRemaining()));
                jsonReader2.setLenient(false);
                final MutableComponent mx3 = Serializer.GSON.<MutableComponent>getAdapter(MutableComponent.class).read(jsonReader2);
                stringReader.setCursor(stringReader.getCursor() + getPos(jsonReader2));
                return mx3;
            }
            catch (IOException | StackOverflowError ex) {
                final Throwable t;
                final Throwable throwable2 = t;
                throw new JsonParseException(throwable2);
            }
        }
        
        private static int getPos(final JsonReader jsonReader) {
            try {
                return Serializer.JSON_READER_POS.getInt(jsonReader) - Serializer.JSON_READER_LINESTART.getInt(jsonReader) + 1;
            }
            catch (IllegalAccessException illegalAccessException2) {
                throw new IllegalStateException("Couldn't read position of JsonReader", illegalAccessException2);
            }
        }
        
        static {
            final GsonBuilder gsonBuilder1;
            GSON = Util.<Gson>make(() -> {
                gsonBuilder1 = new GsonBuilder();
                gsonBuilder1.disableHtmlEscaping();
                gsonBuilder1.registerTypeHierarchyAdapter(Component.class, new Serializer());
                gsonBuilder1.registerTypeHierarchyAdapter(Style.class, new Style.Serializer());
                gsonBuilder1.registerTypeAdapterFactory(new LowerCaseEnumTypeAdapterFactory());
                return gsonBuilder1.create();
            });
            Field field1;
            JSON_READER_POS = Util.<Field>make(() -> {
                try {
                    new JsonReader(new java.io.StringReader(""));
                    field1 = JsonReader.class.getDeclaredField("pos");
                    field1.setAccessible(true);
                    return field1;
                }
                catch (NoSuchFieldException noSuchFieldException1) {
                    throw new IllegalStateException("Couldn't get field 'pos' for JsonReader", noSuchFieldException1);
                }
            });
            Field field2;
            JSON_READER_LINESTART = Util.<Field>make(() -> {
                try {
                    new JsonReader(new java.io.StringReader(""));
                    field2 = JsonReader.class.getDeclaredField("lineStart");
                    field2.setAccessible(true);
                    return field2;
                }
                catch (NoSuchFieldException noSuchFieldException2) {
                    throw new IllegalStateException("Couldn't get field 'lineStart' for JsonReader", noSuchFieldException2);
                }
            });
        }
    }
}
