/* Copyright (c) 2012,
 * Mathias Kuhring, KuhringM@rki.de, Robert Koch-Institut, Germany, 
 * All rights reserved. For details, please note the license.txt.
 */

package de.rki.ng4.ipig.tools;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;

import de.rki.ng4.ipig.exceptions.ExitException;

/**
 * <p>The Configurator improves the {@link Properties} class with static methods (it is usable like a singleton),
 * so configuration parameters are available every in the program.</p>
 * 
 * <p>The Configurator contains two Properties objects, one for "user" parameters which can be saved and loaded (e.g. for parameter control by a user)
 * and one for "system" parameters which can't be saved or loaded (so code intern or temporary use only).</p> 
 * 
 * <p>This class also provides set and check methods for a breakpoint which might be useful for a multi-threaded program,
 * to exit some part of the program properly without killing something in a bad moment (e.g. while streams are open).</p>
 * 
 * @author Mathias Kuhring
 */
public class Configurator {

	private static Properties user = new Properties();
	private static Properties system = new Properties();

	/**
	 * <p>Loads "user" properties from a file.</p>
	 * 
	 * <p>For more informations about how such files look like see {@link Properties}.</p>
	 * 
	 * @param filename name of the properties file
	 * @throws ExitException
	 */
	public static void loadProperties(String filename) throws ExitException{
		try {
			BufferedReader confBuffer = new BufferedReader(new FileReader(new File(filename)));
			user.load(confBuffer);
			confBuffer.close();
		} catch (FileNotFoundException e) {
			throw new ExitException(e.getMessage());
		} catch (IOException e) {
			throw new ExitException(e.getMessage());
		}
	}
	
	/**
	 * <p>Saves "user" properties to a file.</p>
	 * 
	 * @param filename name of the properties file
	 * @throws ExitException
	 */
	public static void saveProperties(String filename) throws ExitException{
		try {
			BufferedWriter confBuffer = new BufferedWriter(new FileWriter(new File(filename)));
			user.store(confBuffer, null);
			confBuffer.close();
		} catch (FileNotFoundException e) {
			throw new ExitException(e.getMessage());
		} catch (IOException e) {
			throw new ExitException(e.getMessage());
		}
	}

	/**
	 * Returns a "user" property indicated by a name (key), if available.
	 * 
	 * @param key name of the property
	 * @return property's value if available, null else
	 */
	public static String getProperty(String key){
		return user.getProperty(key);
	}

	/**
	 * Returns a "user" property indicated by a name (key) or if not available a given default value.
	 * 
	 * @param key name of the property
	 * @param defaultValue a default return value
	 * @return property's value if available, default value else
	 */
	public static String getProperty(String key, String defaultValue){
		return user.getProperty(key, defaultValue);
	}

	/**
	 * Sets a "user"  property indicated by a name (key) with a arbitrary value.
	 * 
	 * @param key name of the property
	 * @param value value for the property
	 */
	public static void setProperty(String key, String value) {
		user.setProperty(key, value);
	}

	/**
	 * Returns all properties, incl. "user" and "system" properties.
	 * 
	 * @return a Properties object containing all properties set or loaded so far
	 */
	public static Properties getProperties() {
		Properties output = new Properties();
		output.putAll(user);
		output.putAll(system);
		return output;
	}
	
	/**
	 * Returns a "system" property indicated by a name (key), if available.
	 * 
	 * @param key name of the property
	 * @return property's value if available, null else
	 */
	public static String getSysProperty(String key){
		return system.getProperty(key);
	}

	/**
	 * Returns a "system" property indicated by a name (key) or if not available a given default value.
	 * 
	 * @param key name of the property
	 * @param defaultValue a default return value
	 * @return property's value if available, default value else
	 */
	public static String getSysProperty(String key, String defaultValue){
		return system.getProperty(key, defaultValue);
	}

	/**
	 * Sets a "system"  property indicated by a name (key) with a arbitrary value.
	 * 
	 * @param key name of the property
	 * @param value value for the property
	 */
	public static void setSysProperty(String key, String value) {
		system.setProperty(key, value);
	}
	
	/**
	 * <p>Sets a breakpoint (or stop signal) which can be used with {@link #checkBreak()}.</p>
	 * 
	 * @param brk true activates the breakpoint
	 */
	public static void setBreak(boolean brk){
		system.setProperty("break", Boolean.toString(brk));
	}
	
	/**
	 * <p>Throws an ExitException if the breakpoint is activated with {@link #setBreak(boolean)}.</p>
	 * 
	 * @throws ExitException
	 */
	public static void checkBreak() throws ExitException{
		if (system.getProperty("break", "false").matches("true")){
			throw new ExitException("stop by user\n");
		}
	}
	
	/**
	 * Removes a "user"  property indicated by a name (key).
	 * 
	 * @param key name of the property to remove
	 */
	public static void removeProperty(String key){
		user.remove(key);
	}
	
	/**
	 * Removes a "system"  property indicated by a name (key).
	 * 
	 * @param key name of the property to remove
	 */
	public static void removeSysProperty(String key){
		system.remove(key);
	}
}
