package net.minecraftforge.common;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.UUID;
import javax.annotation.Nullable;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.io.Files;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import cpw.mods.fml.relauncher.FMLInjectionData;
/**
 * Caches player's last known usernames
 * 
 * Modders should use {@link #getLastKnownUsername(UUID)} to determine a players
 * last known username.
 * For convenience, {@link #getMap()} is provided to get an immutable copy of
 * the caches underlying map.
 */
public final class UsernameCache {
    private static Map map = Maps.newHashMap();
    private static final Charset charset = Charsets.UTF_8;
    private static final File saveFile = new File( /* The minecraft dir */(File) FMLInjectionData.data()[6], "usernamecache.json");
    private static final Gson gson = new GsonBuilder().setPrettyPrinting().create();
    private static final Logger log = LogManager.getLogger(UsernameCache.class);
    private UsernameCache() {}
    /**
     * Set a player's current username
     * 
     * @param uuid
     *            the player's {@link java.util.UUID UUID}
     * @param username
     *            the player's username
     */
    protected static void setUsername(UUID uuid, String username)
    {
        checkNotNull(uuid);
        checkNotNull(username);
        if (username.equals(map.get(uuid))) return;
        map.put(uuid, username);
        save();
    }
    /**
     * Remove a player's username from the cache
     * 
     * @param uuid
     *            the player's {@link java.util.UUID UUID}
     * @return if the cache contained the user
     */
    protected static boolean removeUsername(UUID uuid)
    {
        checkNotNull(uuid);
        if (map.remove(uuid) != null)
        {
            save();
            return true;
        }
        
        return false;
    }
    /**
     * Get the player's last known username
     * 
     * May be null
     * 
     * @param uuid
     *            the player's {@link java.util.UUID UUID}
     * @return the player's last known username, or null if the
     *         cache doesn't have a record of the last username
     */
    @Nullable
    public static String getLastKnownUsername(UUID uuid)
    {
        checkNotNull(uuid);
        return map.get(uuid);
    }
    /**
     * Check if the cache contains the given player's username
     * 
     * @param uuid
     *            the player's {@link java.util.UUID UUID}
     * @return if the cache contains a username for the given player
     */
    public static boolean containsUUID(UUID uuid)
    {
        checkNotNull(uuid);
        return map.containsKey(uuid);
    }
    /**
     * Get an immutable copy of the cache's underlying map
     * 
     * @return the map
     */
    public static Map getMap()
    {
        return ImmutableMap.copyOf(map);
    }
    /**
     * Save the cache to file
     */
    protected static void save()
    {
        new SaveThread(gson.toJson(map)).start();
    }
    /**
     * Load the cache from file
     */
    protected static void load()
    {
        if (!saveFile.exists()) return;
        try
        {
            String json = Files.toString(saveFile, charset);
            Type type = new TypeToken