/*******************************************************************************
 * Copyright (c) 2006 Sybase, Inc. and others.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Sybase, Inc. - initial API and implementation
 *******************************************************************************/
package org.eclipse.jst.jsf.common.ui.internal.utils;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.StringTokenizer;

import org.eclipse.jst.jsf.common.ui.JSFUICommonPlugin;

/**
 * The main purpose of this class is to give better access methods for property
 * and resource bundle access.
 * 
 * @author mengbo
 */
public final class PropertyUtils {

	private static final String ENCODED_CHAR_PERCENT = "%25"; //$NON-NLS-1$
	private static final String ENCODED_CHAR_CARRIAGE_RETURN = "%0d"; //$NON-NLS-1$
	private static final String ENCODED_CHAR_TAB = "%09"; //$NON-NLS-1$
	private static final String ENCODED_CHAR_NEWLINE = "%0a"; //$NON-NLS-1$
	private static final String ENCODED_CHAR_SPACE = "%20"; //$NON-NLS-1$
	private static final String ENCODED_CHAR_COLON = "%3a"; //$NON-NLS-1$
	private static final String ENCODED_CHAR_EQUALS = "%3d"; //$NON-NLS-1$

	
	// WARNING: There can be NO static logging line here since the logger uses
	// this class to figure out the preferences
	// for the logging system. "Logging" an error here would be useless since
	// you might be setting up the logging system
	// via a call to PropertyUtils.getServerProperty() instead it uses
	// "System.err.println".

	// This is the name for the properties file.
	// The prop-name will be prepended to this string....
	private static final String NAME_PROPERTIES = ".props";

	private static final String STR_BOUNDS_END = ".bounds"; // assumes the

	// window name or
	// name list is
	// prepended

	// //////////////////////////////////////////////////////////////////////////
	// Property get methods.
	// //////////////////////////////////////////////////////////////////////////
	/**
	 * @param props
	 * @param key
	 * @param theDefault
	 * @return the property
	 */
	public static String getProperty(Properties props, String key,
			String theDefault) {
		try {
			String value = props.getProperty(key, theDefault);
			if ((value != null) && (value.length() == 0)) {
				value = null;
			}
			// check again for null, since some versions of the jdk ignore the
			// default
			// if an empty property exists.
			if (value == null) {
				value = theDefault;
			}
			return value;
		} catch (Exception ee) {
			return theDefault;
		}
	}

	/**
	 * @param props
	 * @param key
	 * @return the value for key in props, may return null
	 */
	public static String getProperty(Properties props, String key) {
		try {
			String value = props.getProperty(key);
			if ((value != null) && (value.length() == 0)) {
				value = null;
			}
			return value;
		} catch (Exception ee) {
			return null;
		}
	}

	/**
	 * @param props
	 * @param key
	 * @param defaultValue
	 * @param minimumValue
	 * @return the integer property value for key, or defaultValue
	 * if none.  Enforces minimumValue in all cases
	 */
	public static int getPropertyValue(Properties props, String key,
			int defaultValue, int minimumValue) {
		int theValue = getPropertyValue(props, key, defaultValue);

		if (theValue < minimumValue) {
			theValue = minimumValue;
		}
		return theValue;
	}

	/**
	 * @param props
	 * @param key
	 * @param defaultValue
	 * @return the integer value for key in props or defaultValue if none
	 */
	public static int getPropertyValue(Properties props, String key,
			int defaultValue) {
		String stringValue = getProperty(props, key);
		if (stringValue != null) {
			try {
				return Integer.parseInt(stringValue);
			} catch (NumberFormatException ee)// NOPMD
			{
				// the property value maybe an invalid value, the editor should
				// show these to user.
			}
		}
		return defaultValue;
	}

	/**
	 * @param props
	 * @param key
	 * @param defaultValue
	 * @return the long value for key props or defaultValue if none
	 */
	public static long getPropertyLongValue(Properties props, String key,
			long defaultValue) {
		String stringValue = getProperty(props, key);
		if (stringValue != null) {
			try {
				return Long.parseLong(stringValue);
			} catch (NumberFormatException ee)// NOPMD
			{
				// the property value maybe an invalid value, the editor should
				// show these to user.
			}
		}
		return defaultValue;
	}

	/**
	 * @param props
	 * @param key
	 * @param bDefault
	 * @return true if props has a value for key
	 */
	public static boolean isProperty(Properties props, String key,
			boolean bDefault) {
		return getProperty(props, key, "" + bDefault).equals("" + true);
	}

	/**
	 * @param props
	 * @param key
	 * @return the string values in props for key tokenized from
	 * a comma-separated string
	 */
	public static String[] getPropertyStrings(Properties props, String key) {
		String tokenString = getProperty(props, key);

		if (tokenString == null) {
			return new String[0];
		}
        StringTokenizer tokenizer = new StringTokenizer(tokenString, ",");
        String[] pNames = new String[tokenizer.countTokens()];

        for (int ii = 0; ii < pNames.length; ii++) {
        	pNames[ii] = ((String) tokenizer.nextElement()).trim();
        }
        return pNames;
	}

	// //////////////////////////////////////////////////////////////////////////
	// Resource bundle get methods.
	// //////////////////////////////////////////////////////////////////////////
	/**
	 * @param bundle
	 * @param key
	 * @param theDefault
	 * @return the string value from bundle for key or default if none
	 */
	public static String getResourceProperty(ResourceBundle bundle, String key,
			String theDefault) {
		try {
			String value = bundle.getString(key);
			if ((value == null) || (value.length() == 0)) {
				value = theDefault;
			}
			return value;
		} 
		catch(NullPointerException npe)
		{
			return theDefault;
		}
		catch (MissingResourceException mre)
		{
			return theDefault;
		}
		catch (ClassCastException cce)
		{
			return theDefault;
		}
	}

	/**
	 * @param bundle
	 * @param key
	 * @return the value for key in bundle or null if none
	 */
	public static String getResourceProperty(ResourceBundle bundle, String key) {
		try 
		{
			String value = bundle.getString(key);
			if ((value != null) && (value.length() == 0)) 
			{
				value = null;
			}
				return value;
		}
		catch(NullPointerException npe)
		{
			return null;
		}
		catch (MissingResourceException mre)
		{
			return null;
		}
		catch (ClassCastException cce)
		{
			return null;
		}
	}

	/**
	 * @param bundle
	 * @param key
	 * @param defaultValue
	 * @param minimumValue
	 * @return the integer value for key in bundle or defaultValue if none
	 * Enforces minimum value in all cases
	 */
	public static int getResourcePropertyValue(ResourceBundle bundle,
			String key, int defaultValue, int minimumValue) {
		int theValue = getResourcePropertyValue(bundle, key, defaultValue);

		if (theValue < minimumValue) {
			theValue = minimumValue;
		}
		return theValue;
	}

	/**
	 * @param bundle
	 * @param key
	 * @param defaultValue
	 * @return the integer value for key in bundle or defaultValue if  none
	 */
	public static int getResourcePropertyValue(ResourceBundle bundle,
			String key, int defaultValue) {
		String stringValue = getResourceProperty(bundle, key);
		if (stringValue != null) {
			try {
				return Integer.parseInt(stringValue);
			} catch (NumberFormatException ee)// NOPMD
			{
				// the property value maybe an invalid value, the editor should
				// show these to user.
			}
		}
		return defaultValue;
	}

	/**
	 * @param bundle
	 * @param key
	 * @param defaultValue
	 * @return the long value for key in bundle or default value if none
	 */
	public static long getResourcePropertyLongValue(ResourceBundle bundle,
			String key, long defaultValue) {
		String stringValue = getResourceProperty(bundle, key);
		if (stringValue != null) {
			try {
				return Long.parseLong(stringValue);
			} catch (NumberFormatException ee)// NOPMD
			{
				// the property value maybe an invalid value, the editor should
				// show these to user.
			}
		}
		return defaultValue;
	}

	/**
	 * @param bundle
	 * @param key
	 * @param bDefault
	 * @return true if bundle has a value for key
	 */
	public static boolean isResourceProperty(ResourceBundle bundle, String key,
			boolean bDefault) {
		return getResourceProperty(bundle, key, "" + bDefault)
				.equals("" + true);
	}

	// ///////////////////////////////////////////////////////////////////////
	// Property misc routines
	// ///////////////////////////////////////////////////////////////////////
	/**
	 * @param theName
	 * @return the encoded name
	 */
	public static String encodeName(String theName) {
		int theSize = theName.length();
		StringBuffer encoded = new StringBuffer(theSize);
		char ch;

		for (int ii = 0; ii < theSize; ii++) {
			ch = theName.charAt(ii);
			switch (ch) {
			// these are the set of illegal characters in a Property name
			case '=': // %3d
				encoded.append(ENCODED_CHAR_EQUALS);
				break;
			case ':': // %3a
				encoded.append(ENCODED_CHAR_COLON);
				break;
			case ' ': // %20
				encoded.append(ENCODED_CHAR_SPACE);
				break;
			case '\n': // %0a
				encoded.append(ENCODED_CHAR_NEWLINE);
				break;
			case '\t': // %09
				encoded.append(ENCODED_CHAR_TAB);
				break;
			case '\r': // %0d
				encoded.append(ENCODED_CHAR_CARRIAGE_RETURN);
				break;
			case '%': // %25
				// added because its our encoding flag
				encoded.append(ENCODED_CHAR_PERCENT);
				break;
			default:
				encoded.append(ch);
				break;
			}
		}

		return encoded.toString();
	}

	/**
	 * @param theName
	 * @return the decoded name
	 */
	public static String decodeName(String theName) {
		int theSize = theName.length();
		int kk;
		StringBuffer decoded = new StringBuffer(theSize);
		char ch;

		for (int ii = 0; ii < theSize; ii++) {
			ch = theName.charAt(ii);
			if (ch == '%') {
				ch = theName.charAt(++ii);
				kk = Character.digit(ch, 16);
				kk *= 16;
				ch = theName.charAt(++ii);
				kk += Character.digit(ch, 16);
				decoded.append((char) kk);
			} else {
				decoded.append(ch);
			}
		}

		return decoded.toString();
	}

	/**
	 * @param propName
	 * @return the properties
	 * @throws IOException
	 * @throws FileNotFoundException
	 */
	public static Properties openProperties(String propName)
			throws IOException, FileNotFoundException {
		return openProperties(propName, null, true);
	}

	/**
	 * @param propName
	 * @param propDefaults
	 * @return the properties
	 * @throws IOException
	 * @throws FileNotFoundException
	 */
	public static Properties openProperties(String propName,
			Properties propDefaults) throws IOException, FileNotFoundException {
		return openProperties(propName, propDefaults, true);
	}

	/**
	 * @param propName
	 * @param propDefaults
	 * @param bCreatePropertiesPathname
	 * @return the properties
	 * @throws IOException
	 * @throws FileNotFoundException
	 */
	public static Properties openProperties(String propName,
			Properties propDefaults, boolean bCreatePropertiesPathname)
			throws IOException, FileNotFoundException {
		Properties theProperties = new Properties(propDefaults);

		try {
			String propertiesFilename = bCreatePropertiesPathname ? getPropertiesPathname(propName)
					: propName;
			InputStream theStream = new FileInputStream(propertiesFilename);
			theProperties.load(theStream);
			theStream.close();
		} catch (FileNotFoundException ee) {
			if (propDefaults == null) {
				throw ee;
			}
		} catch (IOException ee) {
			if (propDefaults == null) {
				throw ee;
			}
		}

		return theProperties;
	}

	/**
	 * Combines two properties objects, with the second one as the default
	 * properties
	 * 
	 * @param localProperties
	 * @param defaultProperties
	 * @return the combined properties
	 * @throws IOException
	 */
	public static Properties combineProperties(Properties localProperties,
			Properties defaultProperties) throws IOException {
		Properties theNewProperties = new Properties();

		ByteArrayOutputStream os = new ByteArrayOutputStream();
		defaultProperties.store(os, "");
		localProperties.store(os, "");
		byte[] theData = os.toByteArray();
		ByteArrayInputStream is = new ByteArrayInputStream(theData);
		theNewProperties.load(is);

		return theNewProperties;
	}

	/**
	 * @param theFilename
	 * @return the encoded file name
	 */ 
	public static String encodeFilename(String theFilename) {
		// make theFilename legal on the local system....
		String theSeparator = System.getProperty("file.separator");
		// replace all occurrances of the file separator with a ' '
		for (int ii = 0; ii < theSeparator.length(); ii++) {
			char theChar = theSeparator.charAt(ii);
			theFilename = theFilename.replace(theChar, ' ');
		}

		return theFilename;
	}

	/**
	 * @param baseName
	 * @return the properties path
	 */
	public static String getPropertiesPathname(String baseName) {
		if (baseName.endsWith(NAME_PROPERTIES)) {
			return System.getProperty("user.dir")
					+ System.getProperty("file.separator")
					+ encodeFilename(baseName);
		}
        return System.getProperty("user.dir")
        		+ System.getProperty("file.separator")
        		+ encodeFilename(baseName) + NAME_PROPERTIES;
	}

	// /////////////////////////////////////////////////////////////////////////
	// These are generic routines that are used to get/set/save window bounds

	private static final int INSET = 40;

	/**
	 * Set the initial bounds (size & location) of a component. This will get
	 * the location from the preferences file based on the values of the "names"
	 * parameter. These values will be encoded to make a legal properties name,
	 * joined togther with ".", and the value STR_BOUNDS_END will be appended.
	 * The resulting name will be used to obtain the intial bounds value from
	 * the properties file, which will be decoded and the specified component
	 * will then be set to that value.
	 * @param props 
	 * @param theComponent 
	 * @param names 
	 * @param defaultValue 
	 */
	public static void setComponentBounds(Properties props,
			Component theComponent, String names[], String defaultValue) {
		setComponentBounds(props, theComponent, names, defaultValue, false);
	}

	/**
	 * @param props
	 * @param theComponent
	 * @param names
	 * @param defaultValue
	 * @param bEnsureDesktopVisibility
	 */
	public static void setComponentBounds(Properties props,
			Component theComponent, String names[], String defaultValue,
			boolean bEnsureDesktopVisibility) {
		String tmpString = getComponentPropertyName(names, STR_BOUNDS_END);
		setComponentBounds(props, theComponent, tmpString, defaultValue,
				bEnsureDesktopVisibility);
	}

	/**
	 * @param props
	 * @param theComponent
	 * @param thePropertyName
	 * @param defaultValue
	 */
	public static void setComponentBounds(Properties props,
			Component theComponent, String thePropertyName, String defaultValue) {
		setComponentBounds(props, theComponent, thePropertyName, defaultValue,
				false);
	}

	/**
	 * @param props
	 * @param theComponent
	 * @param thePropertyName
	 * @param defaultValue
	 * @param bEnsureDesktopVisibility
	 */
	public static void setComponentBounds(Properties props,
			Component theComponent, String thePropertyName,
			String defaultValue, boolean bEnsureDesktopVisibility) {
		String tmpString = props.getProperty(thePropertyName, defaultValue);
		Rectangle theValue = decodeBounds(tmpString);
		theComponent.setBounds(theValue);
		if (bEnsureDesktopVisibility) {
			// make sure that this component is visible on the desktop...
			// verify that this window is visible...
			Point theLoc = theComponent.getLocation();
			// get width/height of desktop....
			Dimension portSize = new Dimension(Toolkit.getDefaultToolkit()
					.getScreenSize());
			if (theLoc.x > portSize.width) // move it to top
				theLoc.x = INSET;
			if (theLoc.y > portSize.height) // move it to left
				theLoc.y = INSET;
			theComponent.setLocation(theLoc);
		}
	}

	/**
	 * @param props
	 * @param theComponent
	 * @param names
	 */
	public static void saveComponentBounds(Properties props,
			Component theComponent, String names[]) {
		String tmpString = getComponentPropertyName(names, STR_BOUNDS_END);
		saveComponentBounds(props, theComponent, tmpString);
	}

	/**
	 * @param props
	 * @param theComponent
	 * @param thePropertyName
	 */
	public static void saveComponentBounds(Properties props,
			Component theComponent, String thePropertyName) {
		Rectangle theBounds = theComponent.getBounds();
		String theValue = encodeBounds(theBounds);
		props.put(thePropertyName, theValue);
	}

	/**
	 * @param names
	 * @param subsystemName
	 * @return the component property name or ""
	 */
	public static String getComponentPropertyName(String names[],
			String subsystemName) {
		String tmpString = "";

		for (int ii = 0; ii < names.length; ii++) {
			tmpString = tmpString + (ii > 0 ? "." : "")
					+ PropertyUtils.encodeName(names[ii]);
		}
		if (subsystemName.startsWith(".") == false)
			tmpString += ".";
		tmpString = tmpString + subsystemName;
		return tmpString;
	}

	/**
	 * Decode the comma separated values stored in sBounds. This method is
	 * normally called to decode the location/size of a component which has been
	 * saved into a Properties object. See encodeBounds(); Order of items in the
	 * string is (x, y, w, h)
	 * @param sBounds 
	 * @return the rectangle
	 */
	public static Rectangle decodeBounds(String sBounds) {
		int index;
		int ii;
		int theValue[] = new int[4];
		String tmpString;
		String restString = sBounds;

		for (ii = 0; ii < 4; ii++) {
			theValue[ii] = 0;
		}
		try {
			for (ii = 0; ii < 4; ii++) {
				index = restString.indexOf(",");
				if (index > 0) {
					tmpString = restString.substring(0, index);
					restString = restString.substring(index + 1);
				} else {
					tmpString = restString; // should only happen on the last
					// one....
					restString = null; // will cause an exception if not last
					// one...
				}
				theValue[ii] = Integer.valueOf(tmpString).intValue();
			}
		} catch (Exception ee)// NOPMD
		{
			// the property value maybe an invalid value, the editor should show
			// these to user.
		}

		return new Rectangle(theValue[0], theValue[1], theValue[2], theValue[3]);
	}

	/**
	 * * Encode the bounds of a component into a comma separated list * that is
	 * appropriate for storing in a Properties object. * See decodeBounds();
	 * @param rBounds 
	 * @return the encoded bounds
	 */
	public static String encodeBounds(Rectangle rBounds) {
		return "" + rBounds.x + "," + rBounds.y + "," + rBounds.width + ","
				+ rBounds.height;
	}

	/**
	 * Methods for creating Properties objects from strings.
	 * 
	 * Then "Encoded" versions are used on values that are stored into a
	 * properties file (think of them as sub-properties). They do the encoding
	 * necessary to turn a properties object into a string that has legal
	 * "value" syntax (they actually do more than they need to, but its all
	 * non-destructive).
	 * @param thePropertyString 
	 * @return the properties from the string
	 * @throws IOException 
	 */
	public static Properties getPropertiesFromString(String thePropertyString)
			throws IOException {
		if (thePropertyString == null)
			return null;
		ByteArrayInputStream in = new ByteArrayInputStream(thePropertyString
				.getBytes());

		Properties props = new Properties();
		props.load(in); // throws IOException
		in = null;
		return props;
	}

	/**
	 * @param theEncodedPropertyString
	 * @return the properties
	 * @throws IOException
	 */
	public static Properties getPropertiesFromEncodedString(
			String theEncodedPropertyString) throws IOException {
		if (theEncodedPropertyString == null)
			return null;
		return (getPropertiesFromString(decodeName(theEncodedPropertyString)));
	}

	/**
	 * @param theEncodedPropertyString
	 * @return the properties
	 */
	public static Properties encodedStringToProperties(
			String theEncodedPropertyString) {
		try {
			return getPropertiesFromEncodedString(theEncodedPropertyString);
		} catch (IOException ee) {
			return null;
		}
	}

	/**
	 * @param props
	 * @param comment
	 * @return the string
	 * @throws IOException
	 */
	public static String savePropertiesToString(Properties props, String comment)
			throws IOException {
		if (props == null)
			return null;
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		props.store(out, comment);
		String tmpString = out.toString();
		out = null;
		return tmpString;
	}

	/**
	 * @param props
	 * @param comment
	 * @return the encoded string
	 * @throws IOException
	 */
	public static String savePropertiesToEncodedString(Properties props,
			String comment) throws IOException {
		if (props == null)
			return null;
		return encodeName(savePropertiesToString(props, comment));
	}

	/**
	 * @param props
	 * @return the encoded string
	 */
	public static String propertiesToEncodedString(Properties props) {
		try {
			return savePropertiesToEncodedString(props, "");
		} catch (IOException ee)// NOPMD
		{
            JSFUICommonPlugin.getLogger(PropertyUtils.class).error("saving properties", ee);
		}
		return null;
	}
	
	private PropertyUtils()
	{
		// no instantiation
	}
}
