/*
 * This file is part of Sponge, licensed under the MIT License (MIT).
 *
 * Copyright (c) SpongePowered <https://www.spongepowered.org>
 * Copyright (c) contributors
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package org.spongepowered.common.mixin.core.adventure.text;

import net.kyori.adventure.text.AbstractComponent;
import net.kyori.adventure.text.BlockNBTComponent;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.EntityNBTComponent;
import net.kyori.adventure.text.KeybindComponent;
import net.kyori.adventure.text.NBTComponent;
import net.kyori.adventure.text.ScoreComponent;
import net.kyori.adventure.text.SelectorComponent;
import net.kyori.adventure.text.StorageNBTComponent;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.TranslatableComponent;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.NbtComponent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.common.adventure.SpongeAdventure;
import org.spongepowered.common.bridge.adventure.ComponentBridge;
import org.spongepowered.common.bridge.adventure.StyleBridge;

import java.util.ArrayList;
import java.util.List;

@Mixin(AbstractComponent.class)
public abstract class AbstractComponentMixin implements ComponentBridge {
    private MutableComponent bridge$vanillaComponent;

    @Override
    @SuppressWarnings("ConstantConditions")
    public net.minecraft.network.chat.Component bridge$asVanillaComponent() {
        // TODO(adventure): in 1.16 evaluate using an ITextComponent wrapper as a first stage for conversion
        if (this.bridge$vanillaComponent == null) {
            if (this instanceof TextComponent) {
                this.bridge$vanillaComponent = new net.minecraft.network.chat.TextComponent(((TextComponent) this).content());
            } else if (this instanceof TranslatableComponent) {
                final TranslatableComponent $this = (TranslatableComponent) this;
                final List<net.minecraft.network.chat.Component> with = new ArrayList<>($this.args().size());
                for (final Component arg : $this.args()) {
                    with.add(SpongeAdventure.asVanilla(arg));
                }
                this.bridge$vanillaComponent = new net.minecraft.network.chat.TranslatableComponent($this.key(), with.toArray(new Object[0]));
            } else if (this instanceof KeybindComponent) {
                this.bridge$vanillaComponent = new net.minecraft.network.chat.KeybindComponent(((KeybindComponent) this).keybind());
            } else if (this instanceof ScoreComponent) {
                final ScoreComponent $this = (ScoreComponent) this;
                this.bridge$vanillaComponent = new net.minecraft.network.chat.ScoreComponent($this.name(), $this.objective());
                // ((ScoreTextComponent) this.bridge$vanillaComponent).($this.value()); // value removed
            } else if (this instanceof SelectorComponent) {
                this.bridge$vanillaComponent = new net.minecraft.network.chat.SelectorComponent(((SelectorComponent) this).pattern());
            } else if (this instanceof NBTComponent<?, ?>) {
                if (this instanceof BlockNBTComponent) {
                    final BlockNBTComponent $this = (BlockNBTComponent) this;
                    this.bridge$vanillaComponent = new NbtComponent.BlockNbtComponent(
                      $this.pos().asString(),
                      $this.interpret(),
                      $this.nbtPath()
                    );
                } else if (this instanceof EntityNBTComponent) {
                    final EntityNBTComponent $this = (EntityNBTComponent) this;
                    this.bridge$vanillaComponent = new NbtComponent.EntityNbtComponent($this.selector(), $this.interpret(), $this.nbtPath());
                } else if (this instanceof StorageNBTComponent) {
                    // TODO(adventure) 1.16
                }
            }
            for (final Component child : ((Component) this).children()) {
                this.bridge$vanillaComponent.append(SpongeAdventure.asVanilla(child));
            }
            this.bridge$vanillaComponent.setStyle(((StyleBridge) (Object) ((Component) this).style()).bridge$asVanilla());
        }
        // To prevent potential issues with using this mutable component as part of another text component,
        // of if Minecraft or a mod decides to change this text component, we make a deep copy so that this
        // cache and its siblings are not affected (particularly important for TextComponent#setStyle).
        return this.bridge$vanillaComponent.copy();
    }
}

@@ -2532,117 +2532,8 @@
 ) %7B%0A
-        // TODO(adventure): in 1.16 evaluate using an ITextComponent wrapper as a first stage for conversion%0A
     
@@ -3104,37 +3104,58 @@
 add(
-SpongeAdventure.asVanilla(arg
+((ComponentBridge) arg).bridge$asVanillaComponent(
 ));%0A
@@ -3763,113 +3763,8 @@
 ));%0A
-                // ((ScoreTextComponent) this.bridge$vanillaComponent).($this.value()); // value removed%0A
     
@@ -4240,154 +4240,66 @@
 ent(
-%0A                      $this.pos().asString(),%0A                      $this.interpret(),%0A                      $this.nbtPath()%0A                    
+$this.nbtPath(), $this.interpret(), $this.pos().asString()
 );%0A 
@@ -4539,16 +4539,15 @@
 his.
-selector
+nbtPath
 (), 
@@ -4571,23 +4571,24 @@
 , $this.
-nbtPath
+selector
 ());%0A   
@@ -4674,31 +4674,332 @@
     
-// TODO(adventure) 1.16
+final StorageNBTComponent $this = (StorageNBTComponent) this;%0A                    this.bridge$vanillaComponent = new NbtComponent.StorageNbtComponent(%0A                        $this.nbtPath(),%0A                        $this.interpret(),%0A                        SpongeAdventure.asVanilla($this.storage())%0A                    );
 %0A   
@@ -5157,39 +5157,60 @@
 end(
-SpongeAdventure.asVanilla(child
+((ComponentBridge) child).bridge$asVanillaComponent(
 ));%0A

Make deep conversion do a full conversion