package net.oni2;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.StaxDriver;

/**
 * Manages and stores programm settings
 * 
 * @author Christian Illy
 */
public class SettingsManager implements Serializable {

	private static final long serialVersionUID = 8067725289301601179L;

	private static SettingsManager instance = new SettingsManager();

	private HashMap<String, Object> prefs = new HashMap<String, Object>();

	private boolean printNamesNotInMap = false;

	@SuppressWarnings("unused")
	private transient boolean offlineMode = false;
	@SuppressWarnings("unused")
	private transient boolean noCacheUpdate = false;

	/**
	 * Get the singleton instance
	 * 
	 * @return Singleton instance
	 */
	public static SettingsManager getInstance() {
		return instance;
	}

	private static XStream getXStream() {
		XStream xs = new XStream(new StaxDriver());
		xs.alias("Settings", SettingsManager.class);
		return xs;
	}

	/**
	 * Serializes the settings to disk
	 * 
	 * @param settingsFile
	 *            File to write to
	 */
	public void serializeToFile(File settingsFile) {
		try {
			FileOutputStream fos = new FileOutputStream(settingsFile);
			XStream xs = getXStream();
			xs.toXML(this, fos);
			fos.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Deserializes the settings from disk
	 * 
	 * @param settingsFile
	 *            File to read from
	 */
	public static void deserializeFromFile(File settingsFile) {
		try {
			FileInputStream fis = new FileInputStream(settingsFile);
			XStream xs = getXStream();
			Object obj = xs.fromXML(fis);
			if (obj instanceof SettingsManager)
				instance = (SettingsManager) obj;
			fis.close();
		} catch (FileNotFoundException e) {
		} catch (IOException e) {
		}
	}

	/**
	 * Put a string value
	 * 
	 * @param key
	 *            Key for value
	 * @param value
	 *            Value
	 */
	public void put(String key, String value) {
		prefs.put(key, value);
	}

	/**
	 * Put a boolean value
	 * 
	 * @param key
	 *            Key for value
	 * @param value
	 *            Value
	 */
	public void put(String key, boolean value) {
		prefs.put(key, value);
	}

	/**
	 * Put a int value
	 * 
	 * @param key
	 *            Key for value
	 * @param value
	 *            Value
	 */
	public void put(String key, int value) {
		prefs.put(key, value);
	}

	/**
	 * Get a string value
	 * 
	 * @param key
	 *            Key for value
	 * @param def
	 *            Default return value if key does not exist
	 * @return Value
	 */
	public String get(String key, String def) {
		if (prefs.containsKey(key)) {
			if (prefs.get(key) instanceof String)
				return (String) (prefs.get(key));
		}
		if (printNamesNotInMap)
			System.out.println("Settings: Key \"" + key
					+ "\" not in Map, defaulting to \"" + def + "\".");
		return def;
	}

	/**
	 * Get a boolean value
	 * 
	 * @param key
	 *            Key for value
	 * @param def
	 *            Default return value if key does not exist
	 * @return Value
	 */
	public Boolean get(String key, Boolean def) {
		if (prefs.containsKey(key)) {
			if (prefs.get(key) instanceof Boolean)
				return (Boolean) (prefs.get(key));
		}
		if (printNamesNotInMap)
			System.out.println("Settings: Key \"" + key
					+ "\" not in Map, defaulting to \"" + def + "\".");
		return def;
	}

	/**
	 * Get a int value
	 * 
	 * @param key
	 *            Key for value
	 * @param def
	 *            Default return value if key does not exist
	 * @return Value
	 */
	public int get(String key, int def) {
		if (prefs.containsKey(key)) {
			if (prefs.get(key) instanceof Integer)
				return (Integer) (prefs.get(key));
		}
		if (printNamesNotInMap)
			System.out.println("Settings: Key \"" + key
					+ "\" not in Map, defaulting to \"" + def + "\".");
		return def;
	}

	/**
	 * Remove a value
	 * 
	 * @param key
	 *            Key to value to remove
	 */
	public void removeValue(String key) {
		prefs.remove(key);
	}

}
