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 javax.annotation.Nullable;
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 java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;
import java.util.List;
import net.minecraft.ChatFormatting;
import java.util.Iterator;
import com.mojang.brigadier.Message;

public interface Component extends Message, Iterable<Component> {
    Component setStyle(final Style ln);
    
    Style getStyle();
    
    default Component append(final String string) {
        return this.append(new TextComponent(string));
    }
    
    Component append(final Component lf);
    
    String getContents();
    
    default String getString() {
        final StringBuilder stringBuilder2 = new StringBuilder();
        this.stream().forEach(lf -> stringBuilder2.append(lf.getContents()));
        return stringBuilder2.toString();
    }
    
    default String getString(final int integer) {
        final StringBuilder stringBuilder3 = new StringBuilder();
        final Iterator<Component> iterator4 = this.stream().iterator();
        while (iterator4.hasNext()) {
            final int integer2 = integer - stringBuilder3.length();
            if (integer2 <= 0) {
                break;
            }
            final String string6 = iterator4.next().getContents();
            stringBuilder3.append((string6.length() <= integer2) ? string6 : string6.substring(0, integer2));
        }
        return stringBuilder3.toString();
    }
    
    default String getColoredString() {
        final StringBuilder stringBuilder2 = new StringBuilder();
        String string3 = "";
        for (final Component lf5 : this.stream()) {
            final String string4 = lf5.getContents();
            if (!string4.isEmpty()) {
                final String string5 = lf5.getStyle().getLegacyFormatCodes();
                if (!string5.equals(string3)) {
                    if (!string3.isEmpty()) {
                        stringBuilder2.append(ChatFormatting.RESET);
                    }
                    stringBuilder2.append(string5);
                    string3 = string5;
                }
                stringBuilder2.append(string4);
            }
        }
        if (!string3.isEmpty()) {
            stringBuilder2.append(ChatFormatting.RESET);
        }
        return stringBuilder2.toString();
    }
    
    List<Component> getSiblings();
    
    Stream<Component> stream();
    
    default Stream<Component> flatStream() {
        return this.stream().<Component>map(Component::flattenStyle);
    }
    
    default Iterator<Component> iterator() {
        return this.flatStream().iterator();
    }
    
    Component copy();
    
    default Component deepCopy() {
        final Component lf2 = this.copy();
        lf2.setStyle(this.getStyle().copy());
        for (final Component lf3 : this.getSiblings()) {
            lf2.append(lf3.deepCopy());
        }
        return lf2;
    }
    
    default Component withStyle(final Consumer<Style> consumer) {
        consumer.accept(this.getStyle());
        return this;
    }
    
    default Component withStyle(final ChatFormatting... arr) {
        for (final ChatFormatting g6 : arr) {
            this.withStyle(g6);
        }
        return this;
    }
    
    default Component withStyle(final ChatFormatting g) {
        final Style ln3 = this.getStyle();
        if (g.isColor()) {
            ln3.setColor(g);
        }
        if (g.isFormat()) {
            switch (g) {
                case OBFUSCATED: {
                    ln3.setObfuscated(true);
                    break;
                }
                case BOLD: {
                    ln3.setBold(true);
                    break;
                }
                case STRIKETHROUGH: {
                    ln3.setStrikethrough(true);
                    break;
                }
                case UNDERLINE: {
                    ln3.setUnderlined(true);
                    break;
                }
                case ITALIC: {
                    ln3.setItalic(true);
                    break;
                }
            }
        }
        return this;
    }
    
    default Component flattenStyle(final Component lf) {
        final Component lf2 = lf.copy();
        lf2.setStyle(lf.getStyle().flatCopy());
        return lf2;
    }
    
    public static class Serializer implements JsonDeserializer<Component>, JsonSerializer<Component> {
        private static final Gson GSON;
        private static final Field JSON_READER_POS;
        private static final Field JSON_READER_LINESTART;
        
        @Override
        public Component 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();
                Component lf6;
                if (jsonObject5.has("text")) {
                    lf6 = 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 lo11 = (TextComponent)arr9[integer10];
                                if (lo11.getStyle().isEmpty() && lo11.getSiblings().isEmpty()) {
                                    arr9[integer10] = lo11.getText();
                                }
                            }
                        }
                        lf6 = new TranslatableComponent(string7, arr9);
                    }
                    else {
                        lf6 = new TranslatableComponent(string7, new Object[0]);
                    }
                }
                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");
                    }
                    lf6 = new ScoreComponent(GsonHelper.getAsString(jsonObject6, "name"), GsonHelper.getAsString(jsonObject6, "objective"));
                    if (jsonObject6.has("value")) {
                        ((ScoreComponent)lf6).setValue(GsonHelper.getAsString(jsonObject6, "value"));
                    }
                }
                else if (jsonObject5.has("selector")) {
                    lf6 = new SelectorComponent(GsonHelper.getAsString(jsonObject5, "selector"));
                }
                else if (jsonObject5.has("keybind")) {
                    lf6 = 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")) {
                        lf6 = new NbtComponent.BlockNbtComponent(string7, boolean8, GsonHelper.getAsString(jsonObject5, "block"));
                    }
                    else if (jsonObject5.has("entity")) {
                        lf6 = 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");
                        }
                        lf6 = 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) {
                        lf6.append(this.deserialize(jsonArray9.get(integer11), type, jsonDeserializationContext));
                    }
                }
                lf6.setStyle(jsonDeserializationContext.<Style>deserialize(jsonElement, Style.class));
                return lf6;
            }
            if (jsonElement.isJsonArray()) {
                final JsonArray jsonArray10 = jsonElement.getAsJsonArray();
                Component lf6 = null;
                for (final JsonElement jsonElement2 : jsonArray10) {
                    final Component lf7 = this.deserialize(jsonElement2, (Type)jsonElement2.getClass(), jsonDeserializationContext);
                    if (lf6 == null) {
                        lf6 = lf7;
                    }
                    else {
                        lf6.append(lf7);
                    }
                }
                return lf6;
            }
            throw new JsonParseException("Don't know how to turn " + jsonElement + " into a Component");
        }
        
        private void serializeStyle(final Style ln, final JsonObject jsonObject, final JsonSerializationContext jsonSerializationContext) {
            final JsonElement jsonElement5 = jsonSerializationContext.serialize(ln);
            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 lf, final Type type, final JsonSerializationContext jsonSerializationContext) {
            final JsonObject jsonObject5 = new JsonObject();
            if (!lf.getStyle().isEmpty()) {
                this.serializeStyle(lf.getStyle(), jsonObject5, jsonSerializationContext);
            }
            if (!lf.getSiblings().isEmpty()) {
                final JsonArray jsonArray6 = new JsonArray();
                for (final Component lf2 : lf.getSiblings()) {
                    jsonArray6.add(this.serialize(lf2, lf2.getClass(), jsonSerializationContext));
                }
                jsonObject5.add("extra", jsonArray6);
            }
            if (lf instanceof TextComponent) {
                jsonObject5.addProperty("text", ((TextComponent)lf).getText());
            }
            else if (lf instanceof TranslatableComponent) {
                final TranslatableComponent lp6 = (TranslatableComponent)lf;
                jsonObject5.addProperty("translate", lp6.getKey());
                if (lp6.getArgs() != null && lp6.getArgs().length > 0) {
                    final JsonArray jsonArray7 = new JsonArray();
                    for (final Object object11 : lp6.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 (lf instanceof ScoreComponent) {
                final ScoreComponent ll6 = (ScoreComponent)lf;
                final JsonObject jsonObject6 = new JsonObject();
                jsonObject6.addProperty("name", ll6.getName());
                jsonObject6.addProperty("objective", ll6.getObjective());
                jsonObject6.addProperty("value", ll6.getContents());
                jsonObject5.add("score", jsonObject6);
            }
            else if (lf instanceof SelectorComponent) {
                final SelectorComponent lm6 = (SelectorComponent)lf;
                jsonObject5.addProperty("selector", lm6.getPattern());
            }
            else if (lf instanceof KeybindComponent) {
                final KeybindComponent lj6 = (KeybindComponent)lf;
                jsonObject5.addProperty("keybind", lj6.getName());
            }
            else {
                if (!(lf instanceof NbtComponent)) {
                    throw new IllegalArgumentException("Don't know how to serialize " + lf + " as a Component");
                }
                final NbtComponent lk6 = (NbtComponent)lf;
                jsonObject5.addProperty("nbt", lk6.getNbtPath());
                jsonObject5.addProperty("interpret", lk6.isInterpreting());
                if (lf instanceof NbtComponent.BlockNbtComponent) {
                    final NbtComponent.BlockNbtComponent a7 = (NbtComponent.BlockNbtComponent)lf;
                    jsonObject5.addProperty("block", a7.getPos());
                }
                else if (lf instanceof NbtComponent.EntityNbtComponent) {
                    final NbtComponent.EntityNbtComponent b7 = (NbtComponent.EntityNbtComponent)lf;
                    jsonObject5.addProperty("entity", b7.getSelector());
                }
                else {
                    if (!(lf instanceof NbtComponent.StorageNbtComponent)) {
                        throw new IllegalArgumentException("Don't know how to serialize " + lf + " as a Component");
                    }
                    final NbtComponent.StorageNbtComponent c7 = (NbtComponent.StorageNbtComponent)lf;
                    jsonObject5.addProperty("storage", c7.getId().toString());
                }
            }
            return jsonObject5;
        }
        
        public static String toJson(final Component lf) {
            return Serializer.GSON.toJson(lf);
        }
        
        public static JsonElement toJsonTree(final Component lf) {
            return Serializer.GSON.toJsonTree(lf);
        }
        
        @Nullable
        public static Component fromJson(final String string) {
            return GsonHelper.<Component>fromJson(Serializer.GSON, string, Component.class, false);
        }
        
        @Nullable
        public static Component fromJson(final JsonElement jsonElement) {
            return Serializer.GSON.<Component>fromJson(jsonElement, Component.class);
        }
        
        @Nullable
        public static Component fromJsonLenient(final String string) {
            return GsonHelper.<Component>fromJson(Serializer.GSON, string, Component.class, true);
        }
        
        public static Component fromJson(final StringReader stringReader) {
            try {
                final JsonReader jsonReader2 = new JsonReader(new java.io.StringReader(stringReader.getRemaining()));
                jsonReader2.setLenient(false);
                final Component lf3 = Serializer.GSON.<Component>getAdapter(Component.class).read(jsonReader2);
                stringReader.setCursor(stringReader.getCursor() + getPos(jsonReader2));
                return lf3;
            }
            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);
                }
            });
        }
    }
}
