package top.r3944realms.lib39.mixin.minecraft;

import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.storage.ValueInput;
import net.minecraft.world.level.storage.ValueOutput;
import org.jetbrains.annotations.NotNull;
import org.jspecify.annotations.NonNull;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import top.r3944realms.lib39.core.sync.ILib39SyncDataHolder;
import top.r3944realms.lib39.core.sync.ISyncData;
import top.r3944realms.lib39.core.sync.NBTEntitySyncData;import top.r3944realms.lib39.platform.Services;

import java.util.UUID;

/**
 * The type Mixin entity.
 */
@Mixin(Entity.class)
public abstract class MixinEntity implements ILib39SyncDataHolder {
    /**
     * Gets uuid.
     *
     * @return the uuid
     */
    @Shadow public abstract UUID getUUID();

    @Unique
    private CompoundTag lib39$syncData;

    @Override
    public CompoundTag lib39$getSyncData() {
        if (lib39$syncData == null) {
            lib39$syncData = new CompoundTag();
        }
        return lib39$syncData;
    }

    @Override
    public void lib39$setSyncData(CompoundTag tag) {
        this.lib39$syncData = tag;
    }

    @WrapMethod(method = "saveWithoutId")
    private void wrapSave(ValueOutput output, @NonNull Operation<Void> original) {
        Services.PLATFORM.getUtilHelper().getSyncData2Manager().forEach((id, manager) -> {
            ISyncData<?> o = manager.getSyncMap().get(getUUID());
            if (o instanceof NBTEntitySyncData syncData) {
                saveSyncData(syncData);
            }
        });
        original.call(output);
        lib39$injectSaveSyncData(output);
    }

    @WrapMethod(method = "load")
    private void warpLoad(ValueInput input, @NonNull Operation<Void> original) {
       original.call(input);
       lib39$injectLoadSyncData(input);
    }
}
