package common.nbt;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

public class NBTLoader {
	public static NBTTagCompound readGZip(File file) throws IOException {
		DataInputStream in = new DataInputStream(new BufferedInputStream(new GZIPInputStream(new FileInputStream(file))));
		NBTTagCompound tag;

		try {
			tag = read(in, NBTSizeTracker.INFINITE);
		}
		finally {
			in.close();
		}

		return tag;
	}

	public static void writeGZip(NBTTagCompound tag, File file) throws IOException {
		DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new GZIPOutputStream(new FileOutputStream(file))));

		try {
			write(tag, out);
		}
		finally {
			out.close();
		}
	}

//    public static void safeWrite(NBTTagCompound p_74793_0_, File p_74793_1_) throws IOException
//    {
//        File file1 = new File(p_74793_1_.getAbsolutePath() + "_tmp");
//
//        if (file1.exists())
//        {
//            file1.delete();
//        }
//
//        write(p_74793_0_, file1);
//
//        if (p_74793_1_.exists())
//        {
//            p_74793_1_.delete();
//        }
//
//        if (p_74793_1_.exists())
//        {
//            throw new IOException("Failed to delete " + p_74793_1_);
//        }
//        else
//        {
//            file1.renameTo(p_74793_1_);
//        }
//    }

//    public static void write(NBTTagCompound p_74795_0_, File p_74795_1_) throws IOException
//    {
//        DataOutputStream dataoutputstream = new DataOutputStream(new FileOutputStream(p_74795_1_));
//
//        try
//        {
//            write(p_74795_0_, dataoutputstream);
//        }
//        finally
//        {
//            dataoutputstream.close();
//        }
//    }

//    public static NBTTagCompound read(File p_74797_0_) throws IOException
//    {
//        if (!p_74797_0_.exists())
//        {
//            return null;
//        }
//        else
//        {
//            DataInputStream datainputstream = new DataInputStream(new FileInputStream(p_74797_0_));
//            NBTTagCompound nbttagcompound;
//
//            try
//            {
//                nbttagcompound = read(datainputstream, NBTSizeTracker.INFINITE);
//            }
//            finally
//            {
//                datainputstream.close();
//            }
//
//            return nbttagcompound;
//        }
//    }

	public static NBTTagCompound read(DataInputStream in) throws IOException {
		return read(in, NBTSizeTracker.INFINITE);
	}

	public static NBTTagCompound read(DataInput in, NBTSizeTracker tracker) throws IOException {
		NBTBase tag = readType(in, 0, tracker);

		if(tag instanceof NBTTagCompound) {
			return (NBTTagCompound)tag;
		}
		else {
			throw new IOException("Root tag must be a named compound tag");
		}
	}

	public static void write(NBTTagCompound tag, DataOutput out) throws IOException {
		writeTag(tag, out);
	}

	private static void writeTag(NBTBase tag, DataOutput out) throws IOException {
		out.writeByte(tag.getId());

		if(tag.getId() != 0) {
			out.writeUTF("");
			tag.write(out);
		}
	}

	private static NBTBase readType(DataInput in, int depth, NBTSizeTracker tracker) throws IOException {
		byte type = in.readByte();

		if(type == 0) {
			return new NBTTagEnd();
		}
		else {
			in.readUTF();
			NBTBase tag = NBTBase.createNewByType(type);

			tag.read(in, depth, tracker);
			return tag;
		}
	}
}
