package net.minecraft.nbt;

import net.minecraft.CrashReportCategory;
import net.minecraft.ReportedException;
import net.minecraft.CrashReport;
import javax.annotation.Nullable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.File;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.BufferedOutputStream;
import java.util.zip.GZIPOutputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.util.zip.GZIPInputStream;
import java.io.InputStream;

public class NbtIo {
    public static CompoundTag readCompressed(final InputStream inputStream) throws IOException {
        try (final DataInputStream dataInputStream2 = new DataInputStream(new BufferedInputStream(new GZIPInputStream(inputStream)))) {
            return read(dataInputStream2, NbtAccounter.UNLIMITED);
        }
    }
    
    public static void writeCompressed(final CompoundTag le, final OutputStream outputStream) throws IOException {
        try (final DataOutputStream dataOutputStream3 = new DataOutputStream(new BufferedOutputStream(new GZIPOutputStream(outputStream)))) {
            write(le, dataOutputStream3);
        }
    }
    
    public static void write(final CompoundTag le, final File file) throws IOException {
        final DataOutputStream dataOutputStream3 = new DataOutputStream(new FileOutputStream(file));
        try {
            write(le, dataOutputStream3);
        }
        finally {
            dataOutputStream3.close();
        }
    }
    
    @Nullable
    public static CompoundTag read(final File file) throws IOException {
        if (!file.exists()) {
            return null;
        }
        final DataInputStream dataInputStream2 = new DataInputStream(new FileInputStream(file));
        try {
            return read(dataInputStream2, NbtAccounter.UNLIMITED);
        }
        finally {
            dataInputStream2.close();
        }
    }
    
    public static CompoundTag read(final DataInputStream dataInputStream) throws IOException {
        return read(dataInputStream, NbtAccounter.UNLIMITED);
    }
    
    public static CompoundTag read(final DataInput dataInput, final NbtAccounter ln) throws IOException {
        final Tag lu3 = readUnnamedTag(dataInput, 0, ln);
        if (lu3 instanceof CompoundTag) {
            return (CompoundTag)lu3;
        }
        throw new IOException("Root tag must be a named compound tag");
    }
    
    public static void write(final CompoundTag le, final DataOutput dataOutput) throws IOException {
        writeUnnamedTag(le, dataOutput);
    }
    
    private static void writeUnnamedTag(final Tag lu, final DataOutput dataOutput) throws IOException {
        dataOutput.writeByte(lu.getId());
        if (lu.getId() == 0) {
            return;
        }
        dataOutput.writeUTF("");
        lu.write(dataOutput);
    }
    
    private static Tag readUnnamedTag(final DataInput dataInput, final int integer, final NbtAccounter ln) throws IOException {
        final byte byte4 = dataInput.readByte();
        if (byte4 == 0) {
            return EndTag.INSTANCE;
        }
        dataInput.readUTF();
        try {
            return (Tag)TagTypes.getType(byte4).load(dataInput, integer, ln);
        }
        catch (IOException iOException5) {
            final CrashReport j6 = CrashReport.forThrowable(iOException5, "Loading NBT data");
            final CrashReportCategory k7 = j6.addCategory("NBT Tag");
            k7.setDetail("Tag type", byte4);
            throw new ReportedException(j6);
        }
    }
}
