package net.lax1dude.eaglercraft.beta;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

import net.lax1dude.eaglercraft.internal.vfs2.VFile2;
import net.minecraft.src.IProgressUpdate;
import net.minecraft.src.ISaveFormat;
import net.minecraft.src.ISaveHandler;
import net.minecraft.src.MathHelper;
import net.minecraft.src.NBTBase;
import net.minecraft.src.NBTTagCompound;
import net.minecraft.src.SaveFormatComparator;
import net.minecraft.src.WorldInfo;

public class EaglercraftSaveManager implements ISaveFormat {
	
	public final String directory;
	public VFile2 savedir;
	
	public EaglercraftSaveManager(String dir) {
		this.directory = dir;
	}

	@Override
	public String formatName() {
		return "Eaglercraft VFS";
	}

	@Override
	public ISaveHandler getSaveLoader(String s, boolean flag) {
		return new EaglercraftSaveHandler(directory + "/" + s);
	}

	@Override
	public List getWorldList() {
		//progress.displayLoadingString("Loading Worlds...", "just wait a moment");
		ArrayList<SaveFormatComparator> lst = new ArrayList<>();
		this.savedir = new VFile2(directory);

		for(VFile2 t : savedir.listFiles(true)) {
//			if(!t.dirExists()) {
//				break;
//			}
			if(t.getName().contains("lvl")) {
				String folderName = t.getParent();
				String dir = t.getPath();
				VFile2 file = new VFile2(folderName + "/lvl");
				byte[] lvl = file.getAllBytes();
				if (lvl != null) {
					try {
						NBTBase nbt = NBTBase.readTag(new DataInputStream(new ByteArrayInputStream(lvl)));
						if (nbt instanceof NBTTagCompound) {
							WorldInfo w = new WorldInfo((NBTTagCompound) nbt);
							String s1 = w.getWorldName();
							if (s1 == null || MathHelper.stringNullOrLengthZero(s1)) {
								s1 = folderName;
							}
							lst.add(new SaveFormatComparator(folderName, s1, w.getLastTimePlayed(), w.getSizeOnDisk(), false));
						} else {
							throw new IOException("file '" + folderName + "/lvl' does not contain an NBTTagCompound");
						}
					} catch (IOException e) {
						System.err.println("Failed to load world data for '" + directory + "/lvl'");
						System.err.println("It will be kept for future recovery");
						e.printStackTrace();
					}
				}
			}
		}
		return lst;
	}

	@Override
	public void flushCache() {
	}

	@Override
	public WorldInfo getWorldInfoForWorld(String s) {
		this.savedir = new VFile2(directory + "/" + s + "/lvl");
		byte[] lvl = savedir.getAllBytes();
		if(lvl != null) {
			try {
				NBTBase nbt = NBTBase.readTag(new DataInputStream(new ByteArrayInputStream(lvl)));
				if(nbt instanceof NBTTagCompound) {
					return new WorldInfo((NBTTagCompound)nbt);
				}else {
					throw new IOException("file '" + directory + "/" + s + "/lvl' does not contain an NBTTagCompound");
				}
			}catch(IOException e) {
				System.err.println("Failed to load world data for '" + directory + "/lvl'");
				System.err.println("It will be kept for future recovery");
				e.printStackTrace();
			}
		}
		return null;
	}

	public void deleteWorldByDirectory(String s) {
		VFile2 var3 = new VFile2("saves", s);
		System.out.println(var3.getPath());
		if(var3.dirExists()) {
			List<VFile2> files = var3.listFiles(true);
			deleteWorldFiles(files.toArray(new VFile2[0]));
			var3.delete();
		}
	}

	protected static void deleteWorldFiles(VFile2[] var0) {
		for(int var1 = 0; var1 < var0.length; ++var1) {
			var0[var1].delete();
		}
	}

	public boolean isOldMapFormat(String s) {
		return false;
	}

	public boolean convertMapFormat(String s, IProgressUpdate iprogressupdate) {
		return false;
	}

	@Override
	public void renameWorldData(String s, String s1) {
		this.savedir = new VFile2(directory + "/" + s + "/lvl");
		byte[] lvl = savedir.getAllBytes();
		if(lvl != null) {
			try {
				NBTBase nbt = NBTBase.readTag(new DataInputStream(new ByteArrayInputStream(lvl)));
				if(nbt instanceof NBTTagCompound) {
					NBTTagCompound w = (NBTTagCompound)nbt;
					w.setString("LevelName", s1);
					ByteArrayOutputStream out = new ByteArrayOutputStream(lvl.length + 16 + s1.length() * 2); // should be large enough
					NBTBase.writeTag(w, new DataOutputStream(out));
					this.savedir = new VFile2(directory + "/" + s + "/lvl");
					this.savedir.setAllBytes(out.toByteArray());
				}else {
					throw new IOException("file '" + directory + "/" + s + "/lvl' does not contain an NBTTagCompound");
				}
			}catch(IOException e) {
				System.err.println("Failed to load world data for '" + directory + "/lvl'");
				System.err.println("It will be kept for future recovery");
				e.printStackTrace();
			}
		}
	}

}
