package j3deditor.bin.util;

import java.io.File;

import java.util.Enumeration;
import java.util.Hashtable;


/**
 * Tool that loads, saves and manages user preferences.
 *
 * @author Risto Seene
 */
public class UserData{

	/** relative path of the root directory of user files. */
	public static final String dataPath = "userdata";

	/** relative path of the language directory. */
	public static final String languages = UserData.dataPath + File.separator + "lang";

	/** relative path of the resources directory. */
	public static final String resources = UserData.dataPath + File.separator + "resources";

	/** name of the file the default user preferences are stored in */
	private final String defaultSettings = "settings_default.xml";
	
	/** name of the file the user preferences are stored in */
	private final String settings = "settings.xml";


	/** hashtable which contains settings elements and values */
	private Hashtable userdata;

	/** list of available languages */
	private String[][] languageList;


	/**
	 * Creates an instance of <code>Userdata</code>.
	 */
	public UserData(){
		updateLanguageList();

		userdata = new Hashtable();
		loadSettings();
	}


	/**
	 * Updates the list of available languages.
	 */
	public void updateLanguageList(){
		try{
			languageList = Deployer.updateLanguageList(UserData.getFile(UserData.languages));
		} catch(Throwable t){
			Utilities.out.throwWarning(t);
		}
	}


	/**
	 * Loads the settings file using <code>XMLParser</code>
	 */
	private void loadSettings(){
		try{
			XMLParser parser = new XMLParser(UserData.getFile(UserData.dataPath + File.separator + settings));
			loadData(parser);
		} catch(Throwable t){
			try{
				XMLParser parser = new XMLParser(Utilities.util.getResource(Utilities.defaultData + defaultSettings));
				loadData(parser);
			} catch(Throwable t1){
				Utilities.out.throwFatalError("Problem loading " + Utilities.defaultData + defaultSettings);
			}
		}
	}


	/**
	 * Populates the settings elements and values into an
	 * instance of <code>Hashtable</code>.
	 *
	 * @param parser
	 *	an instance of <code>XMLParser</code> that has previously loaded
	 *	the XML file the user preferences are stored in
	 */
	private void loadData(XMLParser parser){
		try{
			String[][] table = parser.getTable();
			for(int i = 0; i < table.length; i++){
				userdata.put(table[i][0], table[i][1]);
			}
		} catch(Throwable t){
			Utilities.out.throwWarning(t);
		}
	}


	/**
	 * Updates the file the user preferences are stored in.
	 */
	public void saveData(){
		try{
			XMLParser parser = new XMLParser();
			String[][] data = new String[userdata.size()][2];
			int i = 0;

			for(Enumeration e = userdata.keys(); e.hasMoreElements(); ){
				Object key = e.nextElement();
				data[i][0] = key.toString();
				data[i][1] = userdata.get(key).toString();
				i++;
			}
			parser.setData(data);

			parser.saveFile(UserData.getFile(UserData.dataPath + File.separator + this.settings));
		} catch(Throwable t){
			Utilities.out.throwWarning(t);
		}
	}


	/**
	 * Returns the list of available languages from the file
	 * the list of languages are stored in.
	 *
	 * @return Returns the list of available languages
	 */
	public String[][] getLanguageList(){
		return languageList;
	}


	/**
	 * Returns the value of the user preferences element
	 * which name is <code>key</code>.
	 *
	 * @param key
	 *	the name of the element
	 * @return Returns <code>Object</code> value of the
	 *	element which name is <code>key</code>
	 */
	public Object getData(String key){
		Object data = null;

		try{
			data = userdata.get(key);
		} catch(Throwable t){
			Utilities.out.throwWarning(t);
		}

		return data;
	}


	/**
	 * Returns the value of the user preferences element
	 * which name is <code>key</code>.
	 *
	 * @param key
	 *	the name of the element
	 * @return Returns <code>boolean</code> value of
	 *	the element which name is <code>key</code>
	 */
	public boolean getBooleanData(String key){
		try{
			String state = getData(key).toString();
			if(state.equals("true")){
				return true;
			}
		} catch(Throwable t){
			Utilities.out.throwError("Invalid setting request: " + key);
		}
		return false;
	}


	/**
	 * Returns the value of the user preferences element
	 * which name is <code>key</code>.
	 *
	 * @param key
	 *	the name of the element
	 * @return Returns <code>int</code> value of
	 *	the element which name is <code>key</code>
	 */
	public int getIntData(String key){
		int nr = 0;
		try{
			String data = getData(key).toString();
			nr = Integer.valueOf(data).intValue();
		} catch(Throwable t){
			Utilities.out.throwError("Invalid setting request: " + key);
		}
		return nr;
	}


	/**
	 * Sets the value of the user preferences element
	 * which name is <code>key</code>.
	 *
	 * @param key
	 *	the name of the element
	 * @param data
	 *	new value
	 */
	public void setData(String key, Object data){
		try{
			userdata.put(key, data);
		} catch(Throwable t){
			Utilities.out.throwWarning(t);
		}
	}
	
	
	/**
	 * Returns the file representation of the given path
	 * relatively to the applications root directory.
	 * 
	 * @param relativePath
	 * 	path of a file somewhere inside the applications root directory.
	 * @return Returns the file representation of the given path
	 * 	relatively to the applications root directory.
	 * @throws Exception
	 * 	if unable to create the required <code>File</code>
	 */
	public static File getFile(String relativePath) throws Exception{
		File root = new File(UserData.class.getProtectionDomain().getCodeSource().getLocation().toURI()).getParentFile();
		return new File(root.getCanonicalPath() + File.separator + relativePath);
	}

}
