/*******************************************************************************
 * Copyright (c) 2000, 2009 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.update.internal.configurator.branding;

import java.io.*;
import java.net.*;
import java.text.MessageFormat; // Can't use ICU, possible launch problem?
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.PropertyResourceBundle;
import java.util.StringTokenizer;

import org.eclipse.core.runtime.*;
import org.eclipse.osgi.util.NLS;
import org.eclipse.update.internal.configurator.Messages;
import org.eclipse.update.internal.configurator.Utils;
import org.osgi.framework.*;

/**
 * Reads the information found in an "INI" file. This file must be in a
 * standard Java properties format. A properties file may also be provided
 * to NL values in the INI file - values must start with the % prefix. A
 * mapping file may also be provided that contains "fill-ins" for the
 * properties file - format being "n = some text", where n is a number.
 */
public class IniFileReader {
	private static final String PID = "org.eclipse.update.configurator"; //$NON-NLS-1$
	private static final Status OK_STATUS = new Status(IStatus.OK, PID, 0, "", null); //$NON-NLS-1$
	private static final String KEY_PREFIX = "%"; //$NON-NLS-1$
	private static final String KEY_DOUBLE_PREFIX = "%%"; //$NON-NLS-1$
	private static final String NLS_TAG = "$nl$"; //$NON-NLS-1$

	private String featureId;
	private String pluginId;
	private String iniFilename;
	private String propertiesFilename;
	private String mappingsFilename;
	private Properties ini = null;
	private PropertyResourceBundle properties = null;
	private String[] mappings = null;
	private Bundle bundle;

	/**
	 * Creates an INI file reader that can parse the contents into key,value pairs.
	 * 
	 * @param featureId the unique identifier of the feature, must not be <code>null</code>
	 * @param pluginId the unique identifier of the feature plug-in, must not be <code>null</code>
	 * @param iniFilename the INI file name, must not be <code>null</code>
	 * @param propertiesFilename the properties filename, can be <code>null</code> if not required
	 * @param mappingsFilename the mappings filename, can be <code>null</code> if not required
	 */
	public IniFileReader(String featureId, String pluginId, String iniFilename, String propertiesFilename, String mappingsFilename) {
		super();
		
		if (featureId == null || pluginId == null || iniFilename == null) {
			throw new IllegalArgumentException();
		}
			
		this.featureId = featureId;
		this.pluginId = pluginId;
		this.iniFilename = iniFilename;
		this.propertiesFilename = propertiesFilename;
		this.mappingsFilename = mappingsFilename;
	}

	/**
	 * Read the contents of the INI, properties, and mappings files.
	 * Does nothing if the content has already been read and parsed.
	 * 
	 * @return an <code>IStatus</code> indicating the success or failure
	 * 	of reading and parsing the INI file content
	 */
	public IStatus load() {
		if (ini != null)
			return OK_STATUS;
			
		// attempt to locate the corresponding plugin
		bundle = Utils.getBundle(pluginId);
		if (bundle == null || bundle.getState() == Bundle.UNINSTALLED || bundle.getState() == Bundle.INSTALLED) {
			bundle = null; // make it null for other test down the road
			String message = NLS.bind(Messages.IniFileReader_MissingDesc, (new String[] { featureId }));
			return new Status(IStatus.ERROR, PID, 0, message, null);
		}

		// Determine the ini file location
		URL iniURL = null;
		IOException ioe = null;
		iniURL = FileLocator.find(bundle, new Path(NLS_TAG).append(iniFilename), null);
		if (iniURL == null) {
			String message = NLS.bind(Messages.IniFileReader_OpenINIError, (new String[] { iniFilename }));
			return new Status(IStatus.ERROR, PID, 0, message, ioe);
		}
		
		// Determine the properties file location
		URL propertiesURL = null;
		if (propertiesFilename != null & propertiesFilename.length() > 0) {
			propertiesURL = FileLocator.find(bundle, new Path(NLS_TAG).append(propertiesFilename), null);
		}

		// Determine the mappings file location
		URL mappingsURL = null;
		if (mappingsFilename != null && mappingsFilename.length() > 0) {
			mappingsURL = FileLocator.find(bundle, new Path(NLS_TAG).append(mappingsFilename), null);
		}

		// OK to pass null properties and/or mapping file
		return load(iniURL, propertiesURL, mappingsURL);
	}
		
	/**
	 * Returns the string value for the given key, or <code>null</code>.
	 * The string value is NLS if requested.
	 * 
	 * @return the string value for the given key, or <code>null</code>
	 */
	public String getString(String key, boolean doNls, Hashtable runtimeMappings) {
		if (ini == null)
			return null;
		String value = ini.getProperty(key);
		if (value != null && doNls)
			return getResourceString(value, runtimeMappings);
		return value;
	}


	/**
	 * Returns a URL for the given key, or <code>null</code>.
	 * 
	 * @return a URL for the given key, or <code>null</code>
	 */
	public URL getURL(String key) {
		if (ini == null)
			return null;

		URL url = null;
		String fileName = ini.getProperty(key);
		if (fileName != null) {
			if (bundle == null)
				return null;
			url = FileLocator.find(bundle, new Path(fileName), null);
		}
		return url;
	}
	
	/**
	 * Returns a array of URL for the given key, or <code>null</code>. The
	 * property value should be a comma separated list of urls, tokens for
	 * which bundle cannot build an url will have a null entry.
	 * 
	 * @param key name of the property containing the requested urls
	 * @return a URL for the given key, or <code>null</code>
	 * @since 3.0
	 */
	public URL[] getURLs(String key) {
		if (ini == null || bundle == null)
			return null;

		String value = ini.getProperty(key);
		if (value == null)
			return null;

		StringTokenizer tokens = new StringTokenizer(value, ","); //$NON-NLS-1$
		ArrayList array = new ArrayList(10);
		while (tokens.hasMoreTokens()) {
			String str = tokens.nextToken().trim();
			array.add(FileLocator.find(bundle, new Path(str), null));
		}

		URL[] urls = new URL[array.size()];
		array.toArray(urls);
		return urls;
	}

	/**
	 * Returns the feature plugin label, or <code>null</code>.
	 * 
	 * @return the feature plugin lable, or <code>null</code> if none.
	 */
	public String getFeaturePluginLabel() {
		if (bundle == null)
			return null;
		return (String)bundle.getHeaders().get(Constants.BUNDLE_NAME);
	}
	
	/**
	 * Returns the provider name for this feature, or <code>null</code>.
	 * 
	 * @return the provider name for this feature, or <code>null</code>
	 */
	public String getProviderName() {
		if (bundle == null)
			return null;
		return (String)bundle.getHeaders().get(Constants.BUNDLE_VENDOR);
	}
	
	/*
	 * Returns a resource string corresponding to the given argument 
	 * value and bundle.
	 * If the argument value specifies a resource key, the string
	 * is looked up in the given resource bundle. If the argument does not
	 * specify a valid key, the argument itself is returned as the
	 * resource string. The key lookup is performed against the
	 * specified resource bundle. If a resource string 
	 * corresponding to the key is not found in the resource bundle
	 * the key value, or any default text following the key in the
	 * argument value is returned as the resource string.
	 * A key is identified as a string begining with the "%" character.
	 * Note that the "%" character is stripped off prior to lookup
	 * in the resource bundle.
	 * <p>
	 * For example, assume resource bundle plugin.properties contains
	 * name = Project Name
	 * <pre>
	 *     <li>getResourceString("Hello World") returns "Hello World"</li>
	 *     <li>getResourceString("%name") returns "Project Name"</li>
	 *     <li>getResourceString("%name Hello World") returns "Project Name"</li>
	 *     <li>getResourceString("%abcd Hello World") returns "Hello World"</li>
	 *     <li>getResourceString("%abcd") returns "%abcd"</li>
	 *     <li>getResourceString("%%name") returns "%name"</li>
	 *     <li>getResourceString(<code>null</code>) returns <code>null</code></li>
	 * </pre>
	 * </p>
	 *
	 * @param value the value or <code>null</code>
	 * @param runtimeMappings runtime mappings or <code>null</code>
	 * @return the resource string
	 */
	 public String getResourceString(String value, Hashtable runtimeMappings) {
		
		if (value == null)
			return null;
		String s = value.trim();

		if (!s.startsWith(KEY_PREFIX))
			return s;

		if (s.startsWith(KEY_DOUBLE_PREFIX))
			return s.substring(1);

		int ix = s.indexOf(" "); //$NON-NLS-1$
		String key = ix == -1 ? s : s.substring(0, ix);
		String dflt = ix == -1 ? s : s.substring(ix + 1);

		if (properties == null)
			return dflt;

		String result = null;
		try {
			result = properties.getString(key.substring(1));
		} catch (MissingResourceException e) {
			return dflt;
		}
		if (runtimeMappings != null) {
			for (Enumeration e = runtimeMappings.keys(); e.hasMoreElements();) {
				String keyValue = (String) e.nextElement();
				int i = result.indexOf(keyValue);
				if (i != -1) {
					String s1 = result.substring(0,i);
					String s2 = (String) runtimeMappings.get(keyValue);
					String s3 = result.substring(i+keyValue.length());
					result = s1 + s2 + s3;
				}
			}
		}
	
		if (result.indexOf('{') != -1) {
			// We test for the curly braces since due to NL issues we do not
			// want to use MessageFormat unless we have to.
			try {
				result = MessageFormat.format(result, mappings);
			} catch (IllegalArgumentException e) {
				//ignore and return string without bound parameters
			}
		}
		
		return result;	
	}

	/*
	 * Read the contents of the ini, properties, and mappings files.
	 */
	private IStatus load(URL iniURL, URL propertiesURL, URL mappingsURL) {

		InputStream is = null;
		try {
			is = iniURL.openStream();
			ini = new Properties();
			ini.load(is);
		} catch (IOException e) {
			ini = null;
			String message = NLS.bind(Messages.IniFileReader_ReadIniError, (new String[] { iniURL.toExternalForm() }));
			return new Status(IStatus.ERROR, PID, 0, message, e);
		} finally {
			try {
				if (is != null)
					is.close();
			} catch (IOException e) {
			}
		}

		if (propertiesURL != null) {
			is = null;
			try {
				is = propertiesURL.openStream();
				properties = new PropertyResourceBundle(is);
			} catch (IOException e) {
				properties = null;
				String message = NLS.bind(Messages.IniFileReader_ReadPropError, (new String[] { propertiesURL.toExternalForm() }));
				return new Status(IStatus.ERROR, PID, 0, message, e);
			} finally {
				try {
					if (is != null)
						is.close();
				} catch (IOException e) {
				}
			}
		}

		PropertyResourceBundle bundle = null;
		if (mappingsURL != null) {
			is = null;
			try {
				is = mappingsURL.openStream();
				bundle = new PropertyResourceBundle(is);
			} catch (IOException e) {
				bundle = null;
				String message = NLS.bind(Messages.IniFileReader_ReadMapError, (new String[] { mappingsURL.toExternalForm() }));
				return new Status(IStatus.ERROR, PID, 0, message, e);
			} finally {
				try {
					if (is != null)
						is.close();
				} catch (IOException e) {
				}
			}
		}

		ArrayList mappingsList = new ArrayList();
		if (bundle != null) {
			boolean found = true;
			int i = 0;
			while (found) {
				try {
					mappingsList.add(bundle.getString(Integer.toString(i)));
				} catch (MissingResourceException e) {
					found = false;
				}
				i++;
			}
		}
		mappings = (String[])mappingsList.toArray(new String[mappingsList.size()]);
		
		return OK_STATUS;
	}
}
