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

import org.osgi.framework.InvalidSyntaxException;

import java.io.*;
import java.net.*;
import java.util.*;

import org.eclipse.core.runtime.*;
import org.eclipse.osgi.framework.log.*;
import org.eclipse.osgi.service.datalocation.*;
import org.eclipse.osgi.service.debug.*;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.osgi.util.NLS;
import org.eclipse.update.configurator.*;
import org.osgi.framework.*;
import org.osgi.service.packageadmin.*;
import org.osgi.service.startlevel.*;

public class ConfigurationActivator implements BundleActivator, IBundleGroupProvider, IConfigurationConstants {

	public static String PI_CONFIGURATOR = "org.eclipse.update.configurator"; //$NON-NLS-1$
	public static final String LAST_CONFIG_STAMP = "last.config.stamp"; //$NON-NLS-1$
	public static final String NAME_SPACE = "org.eclipse.update"; //$NON-NLS-1$
	public static final String UPDATE_PREFIX = "update@"; //$NON-NLS-1$
	private static final String INITIAL_PREFIX = "initial@"; //$NON-NLS-1$

	// debug options
	public static String OPTION_DEBUG = PI_CONFIGURATOR + "/debug"; //$NON-NLS-1$
	// debug values
	public static boolean DEBUG = false;

	private static BundleContext context;
	private ServiceRegistration configurationFactorySR;
	private ServiceRegistration bundleGroupProviderSR;
	private PlatformConfiguration configuration;

	// Location of the configuration data
	private Location configLocation;

	//Need to store that because it is not provided by the platformConfiguration
	private long lastTimeStamp;

	// The expected states timestamp
	private long lastStateTimeStamp;

	// Singleton
	private static ConfigurationActivator configurator;

	public ConfigurationActivator() {
		configurator = this;
	}

	public void start(BundleContext ctx) throws Exception {
		context = ctx;
		loadOptions();
		acquireFrameworkLogService();
		initialize();

		//Short cut, if the configuration has not changed
		if (canRunWithCachedData()) {
			Utils.debug("Running with cached data"); //$NON-NLS-1$
			registerBundleGroupProvider();
			return;
		}

		Utils.debug("Starting update configurator..."); //$NON-NLS-1$

		if (isReconciling())
			installBundles();
		registerBundleGroupProvider();
	}
	
	/**
	 * Returns whether the update configurator should be doing its own reconciling work
	 */
	public static boolean isReconciling() {
		String reconcile = context.getProperty("org.eclipse.update.reconcile"); //$NON-NLS-1$
		return reconcile == null || reconcile.equalsIgnoreCase("true"); //$NON-NLS-1$
		
	}

	private void registerBundleGroupProvider() {
		final String serviceName = IBundleGroupProvider.class.getName();
		try {
			//don't register the service if this bundle has already registered it declaratively
			ServiceReference[] refs = getBundleContext().getServiceReferences(serviceName, null);
			if (refs != null) {
				for (int i = 0; i < refs.length; i++)
					if (PI_CONFIGURATOR.equals(refs[i].getBundle().getSymbolicName()))
						return;
			}
		} catch (InvalidSyntaxException e) {
			//can't happen because we don't pass a filter
		}
		bundleGroupProviderSR = getBundleContext().registerService(serviceName, this, null);
	}

	private void initialize() throws Exception {
		// TODO this test is not really needed any more than any plugin has 
		// to test to see if the runtime is running.  It was there from earlier days
		// where startup was much more disjoint.  Some day that level of decoupling
		// will return but for now...
		if (!Utils.isRunning())
			throw new Exception(Messages.ConfigurationActivator_initialize);

		configLocation = Utils.getConfigurationLocation();
		// create the name space directory for update (configuration/org.eclipse.update)
		if (!configLocation.isReadOnly()) {
			try {
				URL privateURL = new URL(configLocation.getURL(), NAME_SPACE);
				File f = new File(privateURL.getFile());
				if (!f.exists())
					f.mkdirs();
			} catch (MalformedURLException e1) {
				// ignore
			}
		}
		configurationFactorySR = context.registerService(IPlatformConfigurationFactory.class.getName(), new PlatformConfigurationFactory(), null);
		configuration = getPlatformConfiguration(Utils.getInstallURL(), configLocation);
		if (configuration == null)
			throw Utils.newCoreException(NLS.bind(Messages.ConfigurationActivator_createConfig, (new String[] {configLocation.getURL().toExternalForm()})), null);

		DataInputStream stream = null;
		try {
			stream = new DataInputStream(new URL(configLocation.getURL(), NAME_SPACE + '/' + LAST_CONFIG_STAMP).openStream());
			lastTimeStamp = stream.readLong();
			lastStateTimeStamp = stream.readLong();
		} catch (Exception e) {
			lastTimeStamp = configuration.getChangeStamp() - 1;
			lastStateTimeStamp = -1;
		} finally {
			if (stream != null)
				try {
					stream.close();
				} catch (IOException e1) {
					Utils.log(e1.getLocalizedMessage());
				}
		}
	}

	public void stop(BundleContext ctx) throws Exception {
		// quick fix (hack) for bug 47861
		try {
			PlatformConfiguration.shutdown();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		configurationFactorySR.unregister();
		if (bundleGroupProviderSR != null)
			bundleGroupProviderSR.unregister();
		Utils.shutdown();
	}

	public boolean installBundles() {
		Utils.debug("Installing bundles..."); //$NON-NLS-1$
		ServiceReference reference = context.getServiceReference(StartLevel.class.getName());
		int startLevel = 4;
		String defaultStartLevel = context.getProperty("osgi.bundles.defaultStartLevel"); //$NON-NLS-1$
		if (defaultStartLevel != null) {
			try {
				startLevel = Integer.parseInt(defaultStartLevel);
			} catch (NumberFormatException e1) {
				startLevel = 4;
			}
		}
		if (startLevel < 1)
			startLevel = 4;

		StartLevel start = null;
		if (reference != null)
			start = (StartLevel) context.getService(reference);
		try {
			// Get the list of cached bundles and compare with the ones to be installed.
			// Uninstall all the cached bundles that do not appear on the new list
			Bundle[] cachedBundles = context.getBundles();
			URL[] plugins = configuration.getPluginPath();

			// starts the list of bundles to refresh with all currently unresolved bundles (see bug 50680)
			List toRefresh = getUnresolvedBundles();

			Bundle[] bundlesToUninstall = getBundlesToUninstall(cachedBundles, plugins);
			for (int i = 0; i < bundlesToUninstall.length; i++) {
				try {
					if (DEBUG)
						Utils.debug("Uninstalling " + bundlesToUninstall[i].getLocation()); //$NON-NLS-1$
					// include every bundle being uninstalled in the list of bundles to refresh (see bug 82393)					
					toRefresh.add(bundlesToUninstall[i]);
					bundlesToUninstall[i].uninstall();
				} catch (Exception e) {
					Utils.log(NLS.bind(Messages.ConfigurationActivator_uninstallBundle, (new String[] {bundlesToUninstall[i].getLocation()})));
				}
			}

			// Get the urls to install
			String[] bundlesToInstall = getBundlesToInstall(cachedBundles, plugins);
			ArrayList lazyActivationBundles = new ArrayList(bundlesToInstall.length);
			for (int i = 0; i < bundlesToInstall.length; i++) {
				try {
					if (DEBUG)
						Utils.debug("Installing " + bundlesToInstall[i]); //$NON-NLS-1$
					URL bundleURL = new URL("reference:file:" + bundlesToInstall[i]); //$NON-NLS-1$
					//Bundle target = context.installBundle(bundlesToInstall[i]);
					Bundle target = context.installBundle(UPDATE_PREFIX + bundlesToInstall[i], bundleURL.openStream());
					// any new bundle should be refreshed as well
					toRefresh.add(target);
					if (start != null)
						start.setBundleStartLevel(target, startLevel);
					// check the bundle manifest to see if it defines a lazy activation policy
					if (hasLazyActivationPolicy(target))
						lazyActivationBundles.add(target);
				} catch (Exception e) {
					if (!Utils.isAutomaticallyStartedBundle(bundlesToInstall[i]))
						Utils.log(NLS.bind(Messages.ConfigurationActivator_installBundle, (new String[] {bundlesToInstall[i]})) + "   " + e.getMessage()); //$NON-NLS-1$
				}
			}
			context.ungetService(reference);
			removeInitialBundles(toRefresh, cachedBundles);
			refreshPackages((Bundle[]) toRefresh.toArray(new Bundle[toRefresh.size()]));
			// after resolving all the bundles; activate the bundles that have a lazy activation policy
			for (Iterator activateBundles = lazyActivationBundles.iterator(); activateBundles.hasNext();) {
				Bundle toActivate = (Bundle) activateBundles.next();
				try {
					// use the START_ACTIVATION_POLICY option so this is not an eager activation.
					toActivate.start(Bundle.START_ACTIVATION_POLICY);
				} catch (BundleException e) {
					if ((toActivate.getState() & Bundle.RESOLVED) != 0)
						// only log errors if the bundle is resolved
						Utils.log(NLS.bind(Messages.ConfigurationActivator_installBundle, (new String[] {toActivate.getLocation()})) + "   " + e.getMessage()); //$NON-NLS-1$
				}
			}
			// keep track of the last config successfully processed
			writePlatformConfigurationTimeStamp();
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	private static boolean hasLazyActivationPolicy(Bundle target) {
		// check the bundle manifest to see if it defines a lazy activation policy
		Dictionary headers = target.getHeaders(""); //$NON-NLS-1$
		// first check to see if this is a fragment bundle
		String fragmentHost = (String) headers.get(Constants.FRAGMENT_HOST);
		if (fragmentHost != null)
			return false; // do not activate fragment bundles
		// look for the OSGi defined Bundle-ActivationPolicy header
		String activationPolicy = (String) headers.get(Constants.BUNDLE_ACTIVATIONPOLICY);
		try {
			if (activationPolicy != null) {
				ManifestElement[] elements = ManifestElement.parseHeader(Constants.BUNDLE_ACTIVATIONPOLICY, activationPolicy);
				if (elements != null && elements.length > 0) {
					// if the value is "lazy" then it has a lazy activation policy
					if (Constants.ACTIVATION_LAZY.equals(elements[0].getValue()))
						return true;
				}
			} else {
				// check for Eclipse specific lazy start headers "Eclipse-LazyStart" and "Eclipse-AutoStart"
				String eclipseLazyStart = (String) headers.get("Eclipse-LazyStart"); //$NON-NLS-1$
				if (eclipseLazyStart == null)
					eclipseLazyStart = (String) headers.get("Eclipse-AutoStart"); //$NON-NLS-1$
				ManifestElement[] elements = ManifestElement.parseHeader("Eclipse-LazyStart", eclipseLazyStart); //$NON-NLS-1$
				if (elements != null && elements.length > 0) {
					// if the value is true then it is lazy activated
					if ("true".equals(elements[0].getValue())) //$NON-NLS-1$
						return true;
					// otherwise it is only lazy activated if it defines an exceptions directive.
					else if (elements[0].getDirective("exceptions") != null) //$NON-NLS-1$
						return true;
				}
			}
		} catch (BundleException be) {
			// ignore this
		}
		return false;
	}

	private void removeInitialBundles(List bundles, Bundle[] cachedBundles) {
		String[] initialSymbolicNames = getInitialSymbolicNames(cachedBundles);
		Iterator iter = bundles.iterator();
		while (iter.hasNext()) {
			Bundle bundle = (Bundle) iter.next();
			String symbolicName = bundle.getSymbolicName();
			for (int i = 0; i < initialSymbolicNames.length; i++) {
				if (initialSymbolicNames[i].equals(symbolicName)) {
					iter.remove();
					break;
				}
			}
		}
	}

	private String[] getInitialSymbolicNames(Bundle[] cachedBundles) {
		ArrayList initial = new ArrayList();
		for (int i = 0; i < cachedBundles.length; i++) {
			Bundle bundle = cachedBundles[i];
			if (bundle.getLocation().startsWith(INITIAL_PREFIX)) {
				String symbolicName = bundle.getSymbolicName();
				if (symbolicName != null)
					initial.add(symbolicName);
			}
		}
		return (String[]) initial.toArray(new String[initial.size()]);
	}

	private List getUnresolvedBundles() {
		Bundle[] allBundles = context.getBundles();
		List unresolved = new ArrayList();
		for (int i = 0; i < allBundles.length; i++)
			if (allBundles[i].getState() == Bundle.INSTALLED)
				unresolved.add(allBundles[i]);
		return unresolved;
	}

	private String[] getBundlesToInstall(Bundle[] cachedBundles, URL[] newPlugins) {
		// First, create a map of the cached bundles, for faster lookup
		HashSet cachedBundlesSet = new HashSet(cachedBundles.length);
		int offset = UPDATE_PREFIX.length();
		for (int i = 0; i < cachedBundles.length; i++) {
			if (cachedBundles[i].getBundleId() == 0)
				continue; // skip the system bundle
			String bundleLocation = cachedBundles[i].getLocation();
			// Ignore bundles not installed by us
			if (!bundleLocation.startsWith(UPDATE_PREFIX))
				continue;

			bundleLocation = bundleLocation.substring(offset);
			cachedBundlesSet.add(bundleLocation);
			// On windows, we will be doing case insensitive search as well, so lower it now
			if (Utils.isWindows)
				cachedBundlesSet.add(bundleLocation.toLowerCase());
		}

		ArrayList bundlesToInstall = new ArrayList(newPlugins.length);
		for (int i = 0; i < newPlugins.length; i++) {
			String location = Utils.makeRelative(Utils.getInstallURL(), newPlugins[i]).getFile();
			// check if already installed
			if (cachedBundlesSet.contains(location))
				continue;
			if (Utils.isWindows && cachedBundlesSet.contains(location.toLowerCase()))
				continue;

			bundlesToInstall.add(location);
		}
		return (String[]) bundlesToInstall.toArray(new String[bundlesToInstall.size()]);
	}

	private Bundle[] getBundlesToUninstall(Bundle[] cachedBundles, URL[] newPlugins) {
		// First, create a map for faster lookups
		HashSet newPluginsSet = new HashSet(newPlugins.length);
		for (int i = 0; i < newPlugins.length; i++) {

			String pluginLocation = Utils.makeRelative(Utils.getInstallURL(), newPlugins[i]).getFile();
			newPluginsSet.add(pluginLocation);
			// On windows, we will be doing case insensitive search as well, so lower it now
			if (Utils.isWindows)
				newPluginsSet.add(pluginLocation.toLowerCase());
		}

		ArrayList bundlesToUninstall = new ArrayList();
		int offset = UPDATE_PREFIX.length();
		for (int i = 0; i < cachedBundles.length; i++) {
			if (cachedBundles[i].getBundleId() == 0)
				continue; // skip the system bundle
			String cachedBundleLocation = cachedBundles[i].getLocation();
			// Only worry about bundles we installed
			if (!cachedBundleLocation.startsWith(UPDATE_PREFIX))
				continue;
			cachedBundleLocation = cachedBundleLocation.substring(offset);

			if (newPluginsSet.contains(cachedBundleLocation))
				continue;
			if (Utils.isWindows && newPluginsSet.contains(cachedBundleLocation.toLowerCase()))
				continue;

			bundlesToUninstall.add(cachedBundles[i]);
		}
		return (Bundle[]) bundlesToUninstall.toArray(new Bundle[bundlesToUninstall.size()]);
	}

	/**
	 * Creates and starts the platform configuration.
	 * @return the just started platform configuration
	 */
	private PlatformConfiguration getPlatformConfiguration(URL installURL, Location configLocation) {
		try {
			PlatformConfiguration.startup(installURL, configLocation);
		} catch (Exception e) {
			String message = e.getMessage();
			if (message == null)
				message = ""; //$NON-NLS-1$
			Utils.log(Utils.newStatus(message, e));
		}
		return PlatformConfiguration.getCurrent();

	}

	/**
	 * Do PackageAdmin.refreshPackages() in a synchronous way.  After installing
	 * all the requested bundles we need to do a refresh and want to ensure that 
	 * everything is done before returning.
	 * @param bundles
	 */
	private void refreshPackages(Bundle[] bundles) {
		if (bundles.length == 0)
			return;
		ServiceReference packageAdminRef = context.getServiceReference(PackageAdmin.class.getName());
		PackageAdmin packageAdmin = null;
		if (packageAdminRef != null) {
			packageAdmin = (PackageAdmin) context.getService(packageAdminRef);
			if (packageAdmin == null)
				return;
		}
		// TODO this is such a hack it is silly.  There are still cases for race conditions etc
		// but this should allow for some progress...
		// (patch from John A.)
		final boolean[] flag = new boolean[] {false};
		FrameworkListener listener = new FrameworkListener() {
			public void frameworkEvent(FrameworkEvent event) {
				if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED)
					synchronized (flag) {
						flag[0] = true;
						flag.notifyAll();
					}
			}
		};
		context.addFrameworkListener(listener);
		packageAdmin.refreshPackages(bundles);
		synchronized (flag) {
			while (!flag[0]) {
				try {
					flag.wait();
				} catch (InterruptedException e) {
				}
			}
		}
		context.removeFrameworkListener(listener);
		context.ungetService(packageAdminRef);
	}

	private void writePlatformConfigurationTimeStamp() {
		DataOutputStream stream = null;
		try {
			if (configLocation.isReadOnly())
				return;

			String configArea = configLocation.getURL().getFile();
			lastTimeStamp = configuration.getChangeStamp();
			lastStateTimeStamp = Utils.getStateStamp();
			stream = new DataOutputStream(new FileOutputStream(configArea + File.separator + NAME_SPACE + File.separator + LAST_CONFIG_STAMP));
			stream.writeLong(lastTimeStamp);
			stream.writeLong(lastStateTimeStamp);
		} catch (Exception e) {
			Utils.log(e.getLocalizedMessage());
		} finally {
			if (stream != null)
				try {
					stream.close();
				} catch (IOException e1) {
					Utils.log(e1.getLocalizedMessage());
				}
		}
	}

	private void loadOptions() {
		// all this is only to get the application args		
		DebugOptions service = null;
		ServiceReference reference = context.getServiceReference(DebugOptions.class.getName());
		if (reference != null)
			service = (DebugOptions) context.getService(reference);
		if (service == null)
			return;
		try {
			DEBUG = service.getBooleanOption(OPTION_DEBUG, false);
		} finally {
			// we have what we want - release the service
			context.ungetService(reference);
		}
	}

	private boolean canRunWithCachedData() {
		return !"true".equals(context.getProperty("osgi.checkConfiguration")) && //$NON-NLS-1$ //$NON-NLS-2$
				lastTimeStamp == configuration.getChangeStamp() && lastStateTimeStamp == Utils.getStateStamp();
	}

	public static BundleContext getBundleContext() {
		return context;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.runtime.IBundleGroupProvider#getName()
	 */
	public String getName() {
		return Messages.BundleGroupProvider;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.runtime.IBundleGroupProvider#getBundleGroups()
	 */
	public IBundleGroup[] getBundleGroups() {
		if (configuration == null)
			return new IBundleGroup[0];

		IPlatformConfiguration.IFeatureEntry[] features = configuration.getConfiguredFeatureEntries();
		ArrayList bundleGroups = new ArrayList(features.length);
		for (int i = 0; i < features.length; i++) {
			if (features[i] instanceof FeatureEntry && ((FeatureEntry) features[i]).hasBranding())
				bundleGroups.add(features[i]);
		}
		return (IBundleGroup[]) bundleGroups.toArray(new IBundleGroup[bundleGroups.size()]);
	}

	public static ConfigurationActivator getConfigurator() {
		return configurator;
	}

	private void acquireFrameworkLogService() throws Exception {
		ServiceReference logServiceReference = context.getServiceReference(FrameworkLog.class.getName());
		if (logServiceReference == null)
			return;
		Utils.log = (FrameworkLog) context.getService(logServiceReference);
	}
}
