package net.aufdemrand.denizen.objects.notable;
import net.aufdemrand.denizen.objects.*;
import net.aufdemrand.denizen.utilities.DenizenAPI;
import net.aufdemrand.denizen.utilities.debugging.dB;
import net.aufdemrand.denizencore.objects.ObjectFetcher;
import net.aufdemrand.denizencore.objects.dObject;
import net.aufdemrand.denizencore.objects.notable.Notable;
import net.aufdemrand.denizencore.objects.notable.Note;
import net.aufdemrand.denizencore.utilities.CoreUtilities;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
public class NotableManager {
public NotableManager() {
registerWithNotableManager(dCuboid.class);
registerWithNotableManager(dEllipsoid.class);
registerWithNotableManager(dInventory.class);
registerWithNotableManager(dItem.class);
registerWithNotableManager(dLocation.class);
}
public static Map<String, Notable>
notableObjects = new ConcurrentHashMap<String, Notable>();
public static Map<String, Class>
typeTracker = new ConcurrentHashMap<String, Class>();
public static Map<Notable, String>
reverseObjects = new ConcurrentHashMap<Notable, String>();
public static boolean isSaved(String id) {
return notableObjects.containsKey(CoreUtilities.toLowerCase(id));
}
public static boolean isSaved(Notable object) {
return reverseObjects.containsKey(object);
}
public static Notable getSavedObject(String id) {
if (notableObjects.containsKey(CoreUtilities.toLowerCase(id))) {
return notableObjects.get(CoreUtilities.toLowerCase(id));
}
else {
return null;
}
}
public static String getSavedId(Notable object) {
if (reverseObjects.containsKey(object)) {
return reverseObjects.get(object);
}
return null;
}
public static boolean isType(String id, Class type) {
return (typeTracker.containsKey(CoreUtilities.toLowerCase(id)))
&& typeTracker.get(CoreUtilities.toLowerCase(id)) == type;
}
public static void saveAs(Notable object, String id) {
if (object == null) {
return;
}
notableObjects.put(CoreUtilities.toLowerCase(id), object);
reverseObjects.put(object, CoreUtilities.toLowerCase(id));
typeTracker.put(CoreUtilities.toLowerCase(id), object.getClass());
}
public static void remove(String id) {
Notable obj = notableObjects.get(CoreUtilities.toLowerCase(id));
notableObjects.remove(CoreUtilities.toLowerCase(id));
reverseObjects.remove(obj);
typeTracker.remove(CoreUtilities.toLowerCase(id));
}
public static void remove(Notable obj) {
String id = reverseObjects.get(obj);
notableObjects.remove(CoreUtilities.toLowerCase(id));
reverseObjects.remove(obj);
typeTracker.remove(CoreUtilities.toLowerCase(id));
}
public static <T extends dObject> List<T> getAllType(Class<T> type) {
List<T> objects = new ArrayList<T>();
for (Map.Entry<String, Notable> notable : notableObjects.entrySet()) {
// dB.log(notable.toString());
if (isType(notable.getKey(), type)) {
objects.add((T) notable.getValue());
}
}
return objects;
}
/**
* Called on '/denizen reload notables'.
*/
private static void _recallNotables() {
notableObjects.clear();
typeTracker.clear();
reverseObjects.clear();
// Find each type of notable
for (String key : DenizenAPI.getCurrentInstance().notableManager().getNotables().getKeys(false)) {
Class<? extends dObject> clazz = reverse_objects.get(key);
ConfigurationSection section = DenizenAPI.getCurrentInstance().notableManager().getNotables()
.getConfigurationSection(key);
if (section == null) {
continue;
}
for (String notable : section.getKeys(false)) {
Notable obj = (Notable) ObjectFetcher.getObjectFrom(clazz, section.getString(notable));
if (obj != null) {
obj.makeUnique(notable.replace("DOT", "."));
}
else {
dB.echoError("Notable '" + notable.replace("DOT", ".") + "' failed to load!");
}
}
}
}
/**
* Called on by '/denizen save'.
*/
private static void _saveNotables() {
FileConfiguration notables = DenizenAPI.getCurrentInstance().notableManager().getNotables();
for (String key : notables.getKeys(false)) {
notables.set(key, null);
}
for (Map.Entry<String, Notable> notable : notableObjects.entrySet()) {
try {
notables.set(getClassId(getClass(notable.getValue())) + "." + CoreUtilities.toLowerCase(notable.getKey()).replace(".", "DOT"),
notable.getValue().getSaveObject());
}
catch (Exception e) {
dB.echoError("Notable '" + notable.getKey() + "' failed to save!");
dB.echoError(e);
}
}
}
private static <T extends Notable> Class<T> getClass(Notable notable) {
for (Class clazz : objects.keySet()) {
if (clazz.isInstance(notable)) {
return clazz;
}
}
return null;
}
private FileConfiguration notablesSave = null;
private File notablesFile = null;
/**
* Reloads, retrieves and saves notable information from/to 'notables.yml'.
*/
public void reloadNotables() {
if (notablesFile == null) {
notablesFile = new File(DenizenAPI.getCurrentInstance().getDataFolder(), "notables.yml");
}
notablesSave = YamlConfiguration.loadConfiguration(notablesFile);
// Reload notables from notables.yml
_recallNotables();
}
public FileConfiguration getNotables() {
if (notablesSave == null) {
reloadNotables();
}
return notablesSave;
}
public void saveNotables() {
if (notablesSave == null || notablesFile == null) {
return;
}
try {
// Save notables to notables.yml
_saveNotables();
notablesSave.save(notablesFile);
}
catch (IOException ex) {
Logger.getLogger(JavaPlugin.class.getName()).log(Level.SEVERE, "Could not save to " + notablesFile, ex);
}
}
///////////////////
// Note Annotation Handler
///////////////////
private static Map<Class, String> objects = new HashMap<Class, String>();
private static Map<String, Class> reverse_objects = new HashMap<String, Class>();
public static void registerWithNotableManager(Class notable) {
for (Method method : notable.getMethods()) {
if (method.isAnnotationPresent(Note.class)) {
String note = method.getAnnotation(Note.class).value();
objects.put(notable, note);
reverse_objects.put(note, notable);
}
}
}
public static boolean canFetch(Class notable) {
return objects.containsKey(notable);
}
public static String getClassId(Class notable) {
if (canFetch(notable)) {
return objects.get(notable);
}
else {
return null;
}
}
public static Map<String, Class> getReverseClassIdMap() {
return reverse_objects;
}
}