package cn.citycraft.AuthMe.cache.backup;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Type;

import org.bukkit.entity.Player;

import com.google.common.base.Charsets;
import com.google.common.io.Files;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;

import cn.citycraft.AuthMe.ConsoleLogger;
import cn.citycraft.AuthMe.Utils;
import cn.citycraft.AuthMe.settings.Settings;

public class JsonCache {

	private final File cacheDir;
	private final Gson gson;

	public JsonCache() {
		cacheDir = Settings.CACHE_FOLDER;
		if (!cacheDir.exists() && !cacheDir.isDirectory() && !cacheDir.mkdir()) {
			ConsoleLogger.showError("创建缓存目录失败.");
		}
		gson = new GsonBuilder()
				.registerTypeAdapter(DataFileCache.class, new PlayerDataSerializer())
				.registerTypeAdapter(DataFileCache.class, new PlayerDataDeserializer())
				.setPrettyPrinting()
				.create();
	}

	public void createCache(final Player player, final DataFileCache playerData) {
		if (player == null) {
			return;
		}

		String path;
		try {
			path = player.getUniqueId().toString();
		} catch (Exception | Error e) {
			path = player.getName().toLowerCase();
		}

		final File file = new File(cacheDir, path + File.separator + "cache.json");
		if (file.exists()) {
			return;
		}
		if (!file.getParentFile().exists() && !file.getParentFile().mkdirs()) {
			return;
		}

		try {
			final String data = gson.toJson(playerData);
			Files.touch(file);
			Files.write(data, file, Charsets.UTF_8);
		} catch (final IOException e) {
			e.printStackTrace();
		}
	}

	public boolean doesCacheExist(final Player player) {
		String path;
		try {
			path = player.getUniqueId().toString();
		} catch (Exception | Error e) {
			path = player.getName().toLowerCase();
		}
		final File file = new File(cacheDir, path + File.separator + "cache.json");
		return file.exists();
	}

	public DataFileCache readCache(final Player player) {
		String path;
		try {
			path = player.getUniqueId().toString();
		} catch (Exception | Error e) {
			path = player.getName().toLowerCase();
		}

		final File file = new File(cacheDir, path + File.separator + "cache.json");
		if (!file.exists()) {
			return null;
		}

		try {
			final String str = Files.toString(file, Charsets.UTF_8);
			return gson.fromJson(str, DataFileCache.class);
		} catch (final Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	public void removeCache(final Player player) {
		String path;
		try {
			path = player.getUniqueId().toString();
		} catch (Exception | Error e) {
			path = player.getName().toLowerCase();
		}
		final File file = new File(cacheDir, path);
		if (file.exists()) {
			Utils.purgeDirectory(file);
			if (!file.delete()) {
				ConsoleLogger.showError("移除玩家 " + player.getName() + " 缓存数据失败.");
			}
		}
	}

	private static class PlayerDataDeserializer implements JsonDeserializer<DataFileCache> {
		@Override
		public DataFileCache deserialize(final JsonElement jsonElement, final Type type, final JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
			final JsonObject jsonObject = jsonElement.getAsJsonObject();
			if (jsonObject == null) {
				return null;
			}
			JsonElement e;
			String group = null;
			boolean operator = false;
			boolean flying = false;

			if ((e = jsonObject.get("group")) != null) {
				group = e.getAsString();
			}
			if ((e = jsonObject.get("operator")) != null) {
				operator = e.getAsBoolean();
			}
			if ((e = jsonObject.get("flying")) != null) {
				flying = e.getAsBoolean();
			}

			return new DataFileCache(group, operator, flying);
		}
	}

	private class PlayerDataSerializer implements JsonSerializer<DataFileCache> {
		@Override
		public JsonElement serialize(final DataFileCache dataFileCache, final Type type, final JsonSerializationContext jsonSerializationContext) {
			final JsonObject jsonObject = new JsonObject();
			jsonObject.addProperty("group", dataFileCache.getGroup());
			jsonObject.addProperty("operator", dataFileCache.getOperator());
			jsonObject.addProperty("flying", dataFileCache.isFlying());
			return jsonObject;
		}
	}

}
