package net.minecraft.nbt;

import java.util.AbstractList;
import org.apache.logging.log4j.LogManager;
import com.mojang.serialization.DynamicOps;
import com.mojang.serialization.Dynamic;
import net.minecraft.SharedConstants;
import net.minecraft.util.datafix.DataFixTypes;
import com.mojang.datafixers.DataFixer;
import com.google.common.collect.UnmodifiableIterator;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import java.util.Optional;
import net.minecraft.world.level.block.state.StateHolder;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.core.Registry;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SerializableUUID;
import com.google.common.annotations.VisibleForTesting;
import net.minecraft.util.StringUtil;
import javax.annotation.Nullable;
import java.util.Iterator;
import java.util.UUID;
import com.mojang.authlib.properties.Property;
import com.mojang.authlib.GameProfile;
import org.apache.logging.log4j.Logger;

public final class NbtUtils {
    private static final Logger LOGGER;
    
    @Nullable
    public static GameProfile readGameProfile(final CompoundTag le) {
        String string2 = null;
        UUID uUID3 = null;
        if (le.contains("Name", 8)) {
            string2 = le.getString("Name");
        }
        if (le.hasUUID("Id")) {
            uUID3 = le.getUUID("Id");
        }
        try {
            final GameProfile gameProfile4 = new GameProfile(uUID3, string2);
            if (le.contains("Properties", 10)) {
                final CompoundTag le2 = le.getCompound("Properties");
                for (final String string3 : le2.getAllKeys()) {
                    final ListTag lk8 = le2.getList(string3, 10);
                    for (int integer9 = 0; integer9 < lk8.size(); ++integer9) {
                        final CompoundTag le3 = lk8.getCompound(integer9);
                        final String string4 = le3.getString("Value");
                        if (le3.contains("Signature", 8)) {
                            gameProfile4.getProperties().put(string3, new Property(string3, string4, le3.getString("Signature")));
                        }
                        else {
                            gameProfile4.getProperties().put(string3, new Property(string3, string4));
                        }
                    }
                }
            }
            return gameProfile4;
        }
        catch (Throwable t) {
            return null;
        }
    }
    
    public static CompoundTag writeGameProfile(final CompoundTag le, final GameProfile gameProfile) {
        if (!StringUtil.isNullOrEmpty(gameProfile.getName())) {
            le.putString("Name", gameProfile.getName());
        }
        if (gameProfile.getId() != null) {
            le.putUUID("Id", gameProfile.getId());
        }
        if (!gameProfile.getProperties().isEmpty()) {
            final CompoundTag le2 = new CompoundTag();
            for (final String string5 : gameProfile.getProperties().keySet()) {
                final ListTag lk6 = new ListTag();
                for (final Property property8 : gameProfile.getProperties().get(string5)) {
                    final CompoundTag le3 = new CompoundTag();
                    le3.putString("Value", property8.getValue());
                    if (property8.hasSignature()) {
                        le3.putString("Signature", property8.getSignature());
                    }
                    ((AbstractList<CompoundTag>)lk6).add(le3);
                }
                le2.put(string5, lk6);
            }
            le.put("Properties", le2);
        }
        return le;
    }
    
    @VisibleForTesting
    public static boolean compareNbt(@Nullable final Tag lu1, @Nullable final Tag lu2, final boolean boolean3) {
        if (lu1 == lu2) {
            return true;
        }
        if (lu1 == null) {
            return true;
        }
        if (lu2 == null) {
            return false;
        }
        if (!lu1.getClass().equals(lu2.getClass())) {
            return false;
        }
        if (lu1 instanceof CompoundTag) {
            final CompoundTag le4 = (CompoundTag)lu1;
            final CompoundTag le5 = (CompoundTag)lu2;
            for (final String string7 : le4.getAllKeys()) {
                final Tag lu3 = le4.get(string7);
                if (!compareNbt(lu3, le5.get(string7), boolean3)) {
                    return false;
                }
            }
            return true;
        }
        if (!(lu1 instanceof ListTag) || !boolean3) {
            return lu1.equals(lu2);
        }
        final ListTag lk4 = (ListTag)lu1;
        final ListTag lk5 = (ListTag)lu2;
        if (lk4.isEmpty()) {
            return lk5.isEmpty();
        }
        for (int integer6 = 0; integer6 < lk4.size(); ++integer6) {
            final Tag lu4 = lk4.get(integer6);
            boolean boolean4 = false;
            for (int integer7 = 0; integer7 < lk5.size(); ++integer7) {
                if (compareNbt(lu4, lk5.get(integer7), boolean3)) {
                    boolean4 = true;
                    break;
                }
            }
            if (!boolean4) {
                return false;
            }
        }
        return true;
    }
    
    public static IntArrayTag createUUID(final UUID uUID) {
        return new IntArrayTag(SerializableUUID.uuidToIntArray(uUID));
    }
    
    public static UUID loadUUID(final Tag lu) {
        if (lu.getType() != IntArrayTag.TYPE) {
            throw new IllegalArgumentException("Expected UUID-Tag to be of type " + IntArrayTag.TYPE.getName() + ", but found " + lu.getType().getName() + ".");
        }
        final int[] arr2 = ((IntArrayTag)lu).getAsIntArray();
        if (arr2.length != 4) {
            throw new IllegalArgumentException("Expected UUID-Array to be of length 4, but found " + arr2.length + ".");
        }
        return SerializableUUID.uuidFromIntArray(arr2);
    }
    
    public static BlockPos readBlockPos(final CompoundTag le) {
        return new BlockPos(le.getInt("X"), le.getInt("Y"), le.getInt("Z"));
    }
    
    public static CompoundTag writeBlockPos(final BlockPos fu) {
        final CompoundTag le2 = new CompoundTag();
        le2.putInt("X", fu.getX());
        le2.putInt("Y", fu.getY());
        le2.putInt("Z", fu.getZ());
        return le2;
    }
    
    public static BlockState readBlockState(final CompoundTag le) {
        if (!le.contains("Name", 8)) {
            return Blocks.AIR.defaultBlockState();
        }
        final Block bvr2 = Registry.BLOCK.get(new ResourceLocation(le.getString("Name")));
        BlockState cfj3 = bvr2.defaultBlockState();
        if (le.contains("Properties", 10)) {
            final CompoundTag le2 = le.getCompound("Properties");
            final StateDefinition<Block, BlockState> cfk5 = bvr2.getStateDefinition();
            for (final String string7 : le2.getAllKeys()) {
                final net.minecraft.world.level.block.state.properties.Property<?> cgl8 = cfk5.getProperty(string7);
                if (cgl8 != null) {
                    cfj3 = NbtUtils.setValueHelper(cfj3, cgl8, string7, le2, le);
                }
            }
        }
        return cfj3;
    }
    
    private static <S extends StateHolder<?, S>, T extends Comparable<T>> S setValueHelper(final S cfl, final net.minecraft.world.level.block.state.properties.Property<T> cgl, final String string, final CompoundTag le4, final CompoundTag le5) {
        final Optional<T> optional6 = cgl.getValue(le4.getString(string));
        if (optional6.isPresent()) {
            return ((StateHolder<O, S>)cfl).<T, T>setValue(cgl, optional6.get());
        }
        NbtUtils.LOGGER.warn("Unable to read property: {} with value: {} for blockstate: {}", string, le4.getString(string), le5.toString());
        return cfl;
    }
    
    public static CompoundTag writeBlockState(final BlockState cfj) {
        final CompoundTag le2 = new CompoundTag();
        le2.putString("Name", Registry.BLOCK.getKey(cfj.getBlock()).toString());
        final ImmutableMap<net.minecraft.world.level.block.state.properties.Property<?>, Comparable<?>> immutableMap3 = cfj.getValues();
        if (!immutableMap3.isEmpty()) {
            final CompoundTag le3 = new CompoundTag();
            for (final Map.Entry<net.minecraft.world.level.block.state.properties.Property<?>, Comparable<?>> entry6 : immutableMap3.entrySet()) {
                final net.minecraft.world.level.block.state.properties.Property<?> cgl7 = entry6.getKey();
                le3.putString(cgl7.getName(), NbtUtils.getName(cgl7, entry6.getValue()));
            }
            le2.put("Properties", le3);
        }
        return le2;
    }
    
    private static <T extends Comparable<T>> String getName(final net.minecraft.world.level.block.state.properties.Property<T> cgl, final Comparable<?> comparable) {
        return cgl.getName((T)comparable);
    }
    
    public static CompoundTag update(final DataFixer dataFixer, final DataFixTypes aeo, final CompoundTag le, final int integer) {
        return update(dataFixer, aeo, le, integer, SharedConstants.getCurrentVersion().getWorldVersion());
    }
    
    public static CompoundTag update(final DataFixer dataFixer, final DataFixTypes aeo, final CompoundTag le, final int integer4, final int integer5) {
        return (CompoundTag)dataFixer.update(aeo.getType(), new Dynamic((DynamicOps)NbtOps.INSTANCE, le), integer4, integer5).getValue();
    }
    
    static {
        LOGGER = LogManager.getLogger();
    }
}
