package io.papermc.paper.adventure;

import com.mojang.datafixers.util.Pair;
import java.util.function.Function;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.ComponentSerializer;
import net.minecraft.nbt.NbtOps;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.ComponentSerialization;

final class WrapperAwareSerializer implements ComponentSerializer<Component, Component, net.minecraft.network.chat.Component> {
    @Override
    public Component deserialize(final net.minecraft.network.chat.Component input) {
        if (input instanceof AdventureComponent) {
            return ((AdventureComponent) input).adventure;
        }
        final Tag tag = ComponentSerialization.CODEC.encodeStart(NbtOps.INSTANCE, input)
            .get().map(Function.identity(), partial -> {
                throw new RuntimeException("Failed to encode Minecraft Component: " + input + "; " + partial.message());
            });
        final Pair<Component, Tag> converted = AdventureCodecs.COMPONENT_CODEC.decode(NbtOps.INSTANCE, tag)
            .get().map(Function.identity(), partial -> {
                throw new RuntimeException("Failed to decode to adventure Component: " + tag + "; " + partial.message());
            });
        return converted.getFirst();
    }

    @Override
    public net.minecraft.network.chat.Component serialize(final Component component) {
        final Tag tag = AdventureCodecs.COMPONENT_CODEC.encodeStart(NbtOps.INSTANCE, component)
            .get().map(Function.identity(), partial -> {
                throw new RuntimeException("Failed to encode adventure Component: " + component + "; " + partial.message());
            });
        final Pair<net.minecraft.network.chat.Component, Tag> converted = ComponentSerialization.CODEC.decode(NbtOps.INSTANCE, tag)
            .get().map(Function.identity(), partial -> {
                throw new RuntimeException("Failed to decode to Minecraft Component: " + tag + "; " + partial.message());
            });
        return converted.getFirst();
    }
}
