/*******************************************************************************
 * Copyright (c) 2004, 2006 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;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.StringTokenizer;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.osgi.framework.log.FrameworkLog;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.osgi.service.resolver.PlatformAdmin;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.packageadmin.PackageAdmin;
import org.osgi.util.tracker.ServiceTracker;

public class Utils {
	private static final String PROP_ARCH = "osgi.arch"; //$NON-NLS-1$
	private static final String PROP_NL = "osgi.nl"; //$NON-NLS-1$
	private static final String PROP_OS = "osgi.os"; //$NON-NLS-1$
	private static final String PROP_WS = "osgi.ws"; //$NON-NLS-1$
	private static final String PI_OSGI = "org.eclipse.osgi"; //$NON-NLS-1$
	private static final String KEY_PREFIX = "%"; //$NON-NLS-1$
	private static final String KEY_DOUBLE_PREFIX = "%%"; //$NON-NLS-1$
	// os
	public static boolean isWindows = System.getProperty("os.name").startsWith("Win"); //$NON-NLS-1$ //$NON-NLS-2$	
	static FrameworkLog log;
	private static ServiceTracker bundleTracker;
	private static ServiceTracker instanceLocation;
	private static ServiceTracker configurationLocation;

	public static void debug(String s) {
		if (ConfigurationActivator.DEBUG)
			System.out.println("PlatformConfig: " + s); //$NON-NLS-1$
	}
	
	/**
	 * Creates a CoreException from some other exception.
	 * The type of the CoreException is <code>IStatus.ERROR</code>
	 * If the exception passed as a parameter is also a CoreException,
	 * the new CoreException will contain all the status of the passed
	 * CoreException.
	 * 
	 * @see IStatus#ERROR
	 * @param s exception string
	 * @param e actual exception being reported
	 * @return a CoreException
	 * @since 2.0
	 */
	public static CoreException newCoreException(String s, Throwable e) {

		// check the case of a multistatus
		IStatus status;
		if (e instanceof CoreException) {
			if (s == null)
				s = ""; //$NON-NLS-1$
			status = new MultiStatus("org.eclipse.update.configurator", 0, s, e); //$NON-NLS-1$
			IStatus childrenStatus = ((CoreException) e).getStatus();
			((MultiStatus) status).add(childrenStatus);
			((MultiStatus) status).addAll(childrenStatus);
		} else {
			StringBuffer completeString = new StringBuffer(""); //$NON-NLS-1$
			if (s != null)
				completeString.append(s);
			if (e != null) {
				completeString.append(" ["); //$NON-NLS-1$
				String msg = e.getLocalizedMessage();
				completeString.append(msg!=null?msg:e.toString());
				completeString.append("]"); //$NON-NLS-1$
			}
			status = newStatus(completeString.toString(), e);
		}
		return new CoreException(status); 
	}

	public static IStatus newStatus(String message, Throwable e) {
		return new Status(IStatus.ERROR, "org.eclipse.update.configurator", IStatus.OK, message, e); //$NON-NLS-1$
	}
	
	public static void log(String message) {
		log(newStatus(message, null));
	}
	
	public static void log(IStatus status) {
		if (log != null) {
			log.log(new FrameworkLogEntry(ConfigurationActivator.PI_CONFIGURATOR, status.getMessage(), 0, status.getException(), null));
		} else {
			System.out.println(status.getMessage());
			if (status.getException() != null)
				status.getException().printStackTrace();
		}
	}
	
	/**
	 * Returns the url as a platform:/ url, if possible, else leaves it unchanged
	 * @param url
	 * @return
	 */
	public static URL asPlatformURL(URL url) {
		try {
			URL platformURL = new URL("platform:/base/"); //$NON-NLS-1$  // try using platform-relative URL
			URL resolvedPlatformURL = FileLocator.toFileURL(platformURL);
			// TODO workaround bug in platform url resolution
			if (resolvedPlatformURL.getProtocol().equals("file")) //$NON-NLS-1$
				resolvedPlatformURL = new File(resolvedPlatformURL.getFile()).toURL();
			String platformURLAsString = resolvedPlatformURL.toExternalForm();
			String urlAsString = url.toExternalForm();
			if (urlAsString.startsWith(platformURLAsString))
				return new URL(platformURL.toExternalForm() + urlAsString.substring(platformURLAsString.length()) );
			return url;
		} catch (Exception e) {
			return url;
		}
	}
		
	/**
	 * Close the services that we were listening to.
	 */
	/*package*/ static synchronized void shutdown() {
		if (bundleTracker != null) {
			bundleTracker.close();
			bundleTracker = null;
		}
		if (instanceLocation != null) {
			instanceLocation.close();
			instanceLocation = null;
		}		
		if (configurationLocation != null) {
			configurationLocation.close();
			configurationLocation = null;
		}
	}

	/**
	 * Return a boolean value indicating whether or not we consider the
	 * platform to be running.
	 */
	public static boolean isRunning() {
		Bundle bundle = getBundle(PI_OSGI);
		return  bundle == null ? false : bundle.getState() == Bundle.ACTIVE;
	}

	/**
	 * 
	 */
	public static boolean isValidEnvironment(String os, String ws, String arch, String nl) {
		if (os!=null && !isMatching(os, getOS())) return false;
		if (ws!=null && !isMatching(ws, getWS())) return false;
		if (arch!=null && !isMatching(arch, getArch())) return false;
		if (nl!=null && !isMatchingLocale(nl, getNL())) return false;
		return true;
	}
	
	/**
	 * Return the current operating system value.
	 * 
	 * @see EnvironmentInfo#getOS()
	 */
	public static String getOS() {
		return getContext().getProperty(PROP_OS);
	}

	/**
	 * Return the current windowing system value.
	 * 
	 * @see EnvironmentInfo#getWS()
	 */
	public static String getWS() {
		return getContext().getProperty(PROP_WS);
	}

	/**
	 * Return the current system architecture value.
	 * 
	 * @see EnvironmentInfo#getOSArch()
	 */
	public static String getArch() {
		return getContext().getProperty(PROP_ARCH);
	}

	/**
	 * Return the current NL value.
	 * 
	 * @see EnvironmentInfo#getNL()
	 */
	public static String getNL() {
		return getContext().getProperty(PROP_NL);
	}
	
	/**
	 * Returns a number that changes whenever the set of installed plug-ins
	 * changes. This can be used for invalidating caches that are based on 
	 * the set of currently installed plug-ins. (e.g. extensions)
	 * 
	 * @see PlatformAdmin#getState()
	 * @see State#getTimeStamp()
	 */
	public static long getStateStamp() {
		ServiceReference platformAdminReference = getContext().getServiceReference(PlatformAdmin.class.getName());
		if (platformAdminReference == null)
			return -1;
		PlatformAdmin admin = (PlatformAdmin) getContext().getService(platformAdminReference);
		return admin == null ? -1 : admin.getState(false).getTimeStamp();
	}

	/**
	 * Return the resolved bundle with the specified symbolic name.
	 * 
	 * @see PackageAdmin#getBundles(String, String)
	 */
	public static synchronized Bundle getBundle(String symbolicName) {
		if (bundleTracker == null) {
			bundleTracker = new ServiceTracker(getContext(), PackageAdmin.class.getName(), null);
			bundleTracker.open();
		}
		PackageAdmin admin = (PackageAdmin) bundleTracker.getService();
		if (admin == null)
			return null;
		Bundle[] bundles = admin.getBundles(symbolicName, null);
		if (bundles == null)
			return null;
		//Return the first bundle that is not installed or uninstalled
		for (int i = 0; i < bundles.length; i++) {
			if ((bundles[i].getState() & (Bundle.INSTALLED | Bundle.UNINSTALLED)) == 0) {
				return bundles[i];
			}
		}
		return null;
	}

	/*
	 * Return the bundle context for this bundle.
	 */
	private static BundleContext getContext() {
		return ConfigurationActivator.getBundleContext();
	}

	/**
	 * Return the configuration location.
	 * 
	 * @see Location
	 */
	public static synchronized Location getConfigurationLocation() {
		if (configurationLocation == null) {
			Filter filter = null;
			try {
				filter = getContext().createFilter(Location.CONFIGURATION_FILTER);
			} catch (InvalidSyntaxException e) {
				// ignore this. It should never happen as we have tested the above format.
			}
			configurationLocation = new ServiceTracker(getContext(), filter, null);
			configurationLocation.open();
		}
		return (Location) configurationLocation.getService();
	}
	
	/**
	 * 
	 */	
	private static boolean isMatching(String candidateValues, String siteValues) {
		if (siteValues==null) return false;
		if ("*".equalsIgnoreCase(candidateValues)) return true; //$NON-NLS-1$
		siteValues = siteValues.toUpperCase();		
		StringTokenizer stok = new StringTokenizer(candidateValues, ","); //$NON-NLS-1$
		while (stok.hasMoreTokens()) {
			String token = stok.nextToken().toUpperCase();
			if (siteValues.indexOf(token)!=-1) return true;
		}
		return false;
	}
	
	/**
	 * 
	 */	
	private static boolean isMatchingLocale(String candidateValues, String locale) {
		if (locale==null) return false;
		if ("*".equalsIgnoreCase(candidateValues)) return true; //$NON-NLS-1$
		
		locale = locale.toUpperCase();
		candidateValues = candidateValues.toUpperCase();	
		StringTokenizer stok = new StringTokenizer(candidateValues, ","); //$NON-NLS-1$
		while (stok.hasMoreTokens()) {
			String candidate = stok.nextToken();
			if (locale.indexOf(candidate) == 0)
				return true;
			if (candidate.indexOf(locale) == 0)
				return true;
		}
		return false;
	}
	
	public static Locale getDefaultLocale() {
		String nl = getNL();
		// sanity test
		if (nl == null)
			return Locale.getDefault();
		
		// break the string into tokens to get the Locale object
		StringTokenizer locales = new StringTokenizer(nl,"_"); //$NON-NLS-1$
		if (locales.countTokens() == 1)
			return new Locale(locales.nextToken(), ""); //$NON-NLS-1$
		else if (locales.countTokens() == 2)
			return new Locale(locales.nextToken(), locales.nextToken());
		else if (locales.countTokens() == 3)
			return new Locale(locales.nextToken(), locales.nextToken(), locales.nextToken());
		else
			return Locale.getDefault();
	}
	
	
	/**
	 * 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>
	 *     resolveNLString(b,"Hello World") returns "Hello World"</li>
	 *     resolveNLString(b,"%name") returns "Project Name"</li>
	 *     resolveNLString(b,"%name Hello World") returns "Project Name"</li>
	 *     resolveNLString(b,"%abcd Hello World") returns "Hello World"</li>
	 *     resolveNLString(b,"%abcd") returns "%abcd"</li>
	 *     resolveNLString(b,"%%name") returns "%name"</li>
	 * </pre>
	 * </p>
	 * 
	 * @param resourceBundle resource bundle.
	 * @param string translatable string from model
	 * @return string, or <code>null</code>
	 * @since 2.0
	 */
	public static String getResourceString(ResourceBundle resourceBundle, String string) {

		if (string == null)
			return null;

		String s = string.trim();

		if (s.equals("")) //$NON-NLS-1$
			return string;

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

		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 (resourceBundle == null)
			return dflt;

		try {
			return resourceBundle.getString(key.substring(1));
		} catch (MissingResourceException e) {
			return dflt;
		}
	}

	public static boolean isAutomaticallyStartedBundle(String bundleURL) {
		if (bundleURL.indexOf("org.eclipse.osgi") != -1) //$NON-NLS-1$
			return true;
		
		String osgiBundles = ConfigurationActivator.getBundleContext().getProperty("osgi.bundles"); //$NON-NLS-1$
		StringTokenizer st = new StringTokenizer(osgiBundles, ","); //$NON-NLS-1$
		while (st.hasMoreTokens()) {
			String token = st.nextToken().trim();
			int index = token.indexOf('@');
			if (index != -1)
				token = token.substring(0,index);
			if (token.startsWith("reference:file:")) { //$NON-NLS-1$
				File f = new File(token.substring(15));
				if (bundleURL.indexOf(f.getName()) != -1)
					return true;
			}
			if (bundleURL.indexOf(token) != -1)
				return true;
		}
		return false;
	}

	/**
	 * Returns an absolute URL by combining a base absolute URL and another URL relative to the first one.
	 * If the relative URL protocol does not match the base URL protocol, or if the relative URL path is not relative, 
	 * return it as is. 
	 */
	public static URL makeAbsolute(URL base, URL relativeLocation) {
		if (!"file".equals(base.getProtocol())) //$NON-NLS-1$
			// we only deal with file: URLs 
			return relativeLocation;
		if (relativeLocation.getProtocol() != null && !relativeLocation.getProtocol().equals(base.getProtocol()))
			// it is not relative, return as is (avoid creating garbage)
			return relativeLocation;
		IPath relativePath = new Path(relativeLocation.getPath());
		if (relativePath.isAbsolute())
			return relativeLocation;
		try {
			IPath absolutePath = new Path(base.getPath()).append(relativeLocation.getPath());
			// File.toURL() is the best way to create a file: URL
			return absolutePath.toFile().toURL();
		} catch (MalformedURLException e) {
			// cannot happen since we are building from two existing valid URLs
			Utils.log(e.getLocalizedMessage());
			return relativeLocation;
		}
	}

	/**
	 * Returns a URL which is equivalent to the given URL relative to the
	 * specified base URL. Works only for file: URLs
	 */
	public static URL makeRelative(URL base, URL location) {
		if (base == null)
			return location;
		if (!"file".equals(base.getProtocol())) //$NON-NLS-1$
			return location;
		if (!base.getProtocol().equals(location.getProtocol()))
			return location;
		IPath locationPath = new Path(location.getPath());
		if (!locationPath.isAbsolute())
			return location;
		IPath relativePath = makeRelative(new Path(base.getPath()), locationPath);
		try {
			return new URL(base.getProtocol(), base.getHost(), base.getPort(), relativePath.toString());
		} catch (MalformedURLException e) {
			String message = e.getMessage();
			if (message == null)
				message = ""; //$NON-NLS-1$
			Utils.log(Utils.newStatus(message, e));
		}
		return location;
	}

	/**
	 * Returns a path which is equivalent to the given location relative to the
	 * specified base path.
	 */
	public static IPath makeRelative(IPath base, IPath location) {
		if (location.getDevice() != null && !location.getDevice().equalsIgnoreCase(base.getDevice()))
			return location;
		int baseCount = base.segmentCount();
		int count = base.matchingFirstSegments(location);
		String temp = ""; //$NON-NLS-1$
		for (int j = 0; j < baseCount - count; j++)
			temp += "../"; //$NON-NLS-1$
		return new Path(temp).append(location.removeFirstSegments(count));
	}

	/**
	 * Returns a string URL which is equivalent to the given absolute location 
	 * made relative to the specified base path.
	 */
	public static String makeRelative(URL base, String absolute) {
		try {
			return makeRelative(base, new URL(absolute)).toExternalForm();
		} catch (MalformedURLException e) {
			// returns the original string if is invalid
			return absolute;
		}
	}

	/**
	 * Ensures file: URLs on Windows have the right form (i.e. '/' as segment separator, drive letter in lower case, etc)
	 */
	public static String canonicalizeURL(String url) {
		if (!(isWindows && url.startsWith("file:"))) //$NON-NLS-1$
			return url;
		try {
			String path = new URL(url).getPath();			
	        // normalize to not have leading / so we can check the form
	        File file = new File(path);
	        path = file.toString().replace('\\', '/');
            if (Character.isUpperCase(path.charAt(0))) {
                char[] chars = path.toCharArray();
                chars[0] = Character.toLowerCase(chars[0]);
                path = new String(chars);
                return new File(path).toURL().toExternalForm();
            }
		} catch (MalformedURLException e) {
			// default to original url
		}		
		return url;
	}	

	/**
	 * Return the install location.
	 * 
	 * @see Location
	 */
	public static synchronized URL getInstallURL() {
		if (instanceLocation == null) {
			Filter filter = null;
			try {
				filter = getContext().createFilter(Location.INSTALL_FILTER);
			} catch (InvalidSyntaxException e) {
				// ignore this. It should never happen as we have tested the
				// above format.
			}
			instanceLocation = new ServiceTracker(getContext(), filter, null);
			instanceLocation.open();
		}

		Location location = (Location) instanceLocation.getService();

		// it is pretty much impossible for the install location to be null.  If it is, the
		// system is in a bad way so throw and exception and get the heck outta here.
		if (location == null)
			throw new IllegalStateException("The installation location must not be null"); //$NON-NLS-1$

		return  location.getURL();
	}

}
