package org.eclipse.update.configurator;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import org.eclipse.core.runtime.*;
import org.eclipse.osgi.service.environment.DebugOptions;
import org.eclipse.osgi.service.environment.EnvironmentInfo;
import org.osgi.framework.*;
import org.osgi.service.packageadmin.PackageAdmin;
import org.osgi.service.startlevel.StartLevel;
import org.osgi.util.tracker.ServiceTracker;
public class ConfigurationActivator implements BundleActivator {
	private final static String DEFAULT_CONVERTER = "org.eclipse.update.configurator.migration.PluginConverter"; //$NON-NLS-1$
	public static String PI_CONFIGURATOR = "org.eclipse.update.configurator";
	// debug options
	public static String OPTION_DEBUG = PI_CONFIGURATOR + "/debug";
	public static String OPTION_DEBUG_CONVERTER = PI_CONFIGURATOR
			+ "/converter/debug";
	// debug values
	public static boolean DEBUG = false;
	public static boolean DEBUG_CONVERTER = false;
	private static BundleContext context;
	private ServiceTracker platformTracker;
	private ServiceRegistration configurationFactorySR;
	private String[] allArgs;
	// location used to put the generated manfests
	private String cacheLocation = (String) System.getProperties().get(
			"osgi.manifest.cache"); //PASCAL Need to set this value somewhere (probably from boot)
	private IPluginConverter converter;
	private Set ignore;
	private BundleListener reconcilerListener;
	public void start(BundleContext ctx) throws Exception {
		context = ctx;
		loadOptions();
		if (DEBUG)
			System.out.println("Starting update configurator...");
		computeIgnoredBundles();
		loadConverter();
		obtainArgs();
		installBundles();
	}
	private void computeIgnoredBundles() {
		String ignoreList = System
				.getProperty("eclipse.ignore",
						"org.eclipse.osgi,org.eclipse.core.boot,org.eclipse.core.runtime.adaptor");
		ignore = new HashSet();
		StringTokenizer tokenizer = new StringTokenizer(ignoreList, ",");
		while (tokenizer.hasMoreTokens())
			ignore.add(tokenizer.nextToken().trim());
	}
	private boolean shouldIgnore(String bundleName) {
		if (ignore == null)
			return false;
		StringTokenizer tokenizer = new StringTokenizer(bundleName, "._");
		String partialName = "";
		while (tokenizer.hasMoreTokens()) {
			partialName += tokenizer.nextToken();
			if (ignore.contains(partialName))
				return true;
			partialName += ".";
		}
		return false;
	}
	private void loadConverter() {
		// TODO look at making this an extension
		String converterClassName = System.getProperty(
				"eclipse.manifestconverter", DEFAULT_CONVERTER);
		if (converterClassName == null)
			return;
		Class converterClass;
		try {
			converterClass = Class.forName(converterClassName);
		} catch (ClassNotFoundException e) {
			return;
		}
		try {
			converter = (IPluginConverter) converterClass.newInstance();
		} catch (InstantiationException e1) {
			return;
		} catch (IllegalAccessException e1) {
			return;
		} catch (ClassCastException cce) {
			return;
		}
	}
	private void obtainArgs() {
		// all this is only to get the application args		
		EnvironmentInfo envInfo = null;
		ServiceReference envInfoSR = context
				.getServiceReference(EnvironmentInfo.class.getName());
		if (envInfoSR != null)
			envInfo = (EnvironmentInfo) context.getService(envInfoSR);
		if (envInfo == null)
			throw new IllegalStateException();
		this.allArgs = envInfo.getAllArgs();
		// we have what we want - release the service
		context.ungetService(envInfoSR);
	}
	public void stop(BundleContext ctx) throws Exception {
		releasePlatform();
		configurationFactorySR.unregister();
	}
	private void releasePlatform() {
		if (platformTracker == null)
			return;
		platformTracker.close();
		platformTracker = null;
	}
	private IPlatform acquirePlatform() {
		if (platformTracker == null) {
			platformTracker = new ServiceTracker(context, IPlatform.class
					.getName(), null);
			platformTracker.open();
		}
		IPlatform result = (IPlatform) platformTracker.getService();
		while (result == null) {
			try {
				platformTracker.waitForService(1000);
				result = (IPlatform) platformTracker.getService();
			} catch (InterruptedException ie) {
			}
		}
		return result;
	}
private void installBundles() {
		IPlatform platform = acquirePlatform();

		String metaPath = platform.getLocation().append(".metadata").toOSString();
		URL installURL = platform.getInstallURL();
		ServiceReference reference = context.getServiceReference(StartLevel.class.getName());
		StartLevel start = null;
		if (reference != null) 
			start = (StartLevel) context.getService(reference);
		try {
			configurationFactorySR = context.registerService(IPlatformConfigurationFactory.class.getName(), new PlatformConfigurationFactory(), null);
			PlatformConfiguration config = getPlatformConfiguration(allArgs, metaPath, installURL);
			URL[] plugins = config.getPluginPath();
			ArrayList installed = new ArrayList(plugins.length);
			for (int i = 0; i < plugins.length; i++) {
				try {
				String location = plugins[i].toExternalForm();
				checkOrGenerateManifest(location);
				location = "reference:" + location.substring(0, location.lastIndexOf('/'));
				if (!isInstalled(location)) {
					try {
						Bundle target = context.installBundle(location);
						installed.add(target);
						if (start != null)
							start.setBundleStartLevel(target, 4);
					} catch (Exception e) {
						System.err.println("Ignoring bundle at: " + location);
						System.err.println(e.getMessage());
					}
				}
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			context.ungetService(reference);
			refreshPackages((Bundle[]) installed.toArray(new Bundle[installed.size()]));
			if (System.getProperty("eclipse.application") == null || System.getProperty("eclipse.application").equals(PlatformConfiguration.RECONCILER_APP))
				System.setProperty("eclipse.application", config.getApplicationIdentifier());
//			if (config.getApplicationIdentifier().equals(PlatformConfiguration.RECONCILER_APP) ) {
//				reconcilerListener = reconcilerListener();
//				context.addBundleListener(reconcilerListener);
//			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			releasePlatform();
		}
	}	private BundleListener reconcilerListener() {
		return new BundleListener() {
			public void bundleChanged(BundleEvent event) {
				String buid = event.getBundle().getUniqueId();
				if (event.getType() == BundleEvent.STOPPED && buid != null
						&& buid.equals("org.eclipse.update.core"))
					runPostReconciler();
			}
		};
	}
	private void runPostReconciler() {
		Runnable postReconciler = new Runnable() {
			public void run() {
				try {
					Bundle apprunner = context
							.getBundle("org.eclipse.core.applicationrunner");
					apprunner.stop();
					context.removeBundleListener(reconcilerListener);
					try {
						PlatformConfiguration.shutdown();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					installBundles();
					apprunner.start();
				} catch (BundleException be) {
					be.printStackTrace();
				}
			}
		};
		new Thread(postReconciler, "Post reconciler").start();
	}
	/**
	 * @param location
	 */
	private void checkOrGenerateManifest(String pluginManifestLocationURL) {
		if (converter == null)
			return;
		String pluginManifestLocation = null;
		try {
			pluginManifestLocation = new URL(pluginManifestLocationURL)
					.getPath();
		} catch (MalformedURLException e) {
			return;
		}
		File pluginDir = new File(pluginManifestLocation).getParentFile();
		if (shouldIgnore(pluginDir.getName()))
			return;
		File manifest = new File(pluginDir, "META-INF/MANIFEST.MF");
		if (manifest.exists())
			return;
		// bail if the install location is not writable and we don't know where else to write to
		if (cacheLocation == null)
			return;
		File generationLocation = new File(cacheLocation,
				computeFileName(pluginDir.getPath()) + ".MF");
		if (generationLocation.exists())
			return;
		if (!converter.convertManifest(pluginDir, generationLocation))
			System.out.println(pluginDir + " manifest generation failed");
	}
	/*
	 * Derives a file name corresponding to a path:
	 * c:\autoexec.bat -> c__autoexec.bat
	 */
	private String computeFileName(String filePath) {
		StringBuffer newName = new StringBuffer(filePath);
		for (int i = 0; i < filePath.length(); i++) {
			char c = newName.charAt(i);
			if (c == ':' || c == '/' || c == '\\')
				newName.setCharAt(i, '_');
		}
		return newName.toString();
	}
	/**
	 * This is a major hack to try to get the reconciler application running. However we should find a way to not run it.
	 * @param args
	 * @param metaPath
	 * @return
	 */
	private PlatformConfiguration getPlatformConfiguration(String[] args,
			String metaPath, URL installURL) {
		try {
			PlatformConfiguration.startup(args, null, null, metaPath,
					installURL);
		} catch (Exception e) {
			if (platformTracker != null) {
				String message = e.getMessage();
				if (message == null)
					message = "";
				IStatus status = new Status(IStatus.ERROR,
						IPlatform.PI_RUNTIME, IStatus.OK, message, e);
				((IPlatform) platformTracker.getService()).getLog(
						context.getBundle()).log(status);
			}
		}
		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...
		final Object semaphore = new Object();
		FrameworkListener listener = new FrameworkListener() {
			public void frameworkEvent(FrameworkEvent event) {
				if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED)
					synchronized (semaphore) {
						semaphore.notifyAll();
					}
			}
		};
		context.addFrameworkListener(listener);
		packageAdmin.refreshPackages(bundles);
		synchronized (semaphore) {
			try {
				semaphore.wait();
			} catch (InterruptedException e) {
			}
		}
		context.removeFrameworkListener(listener);
		context.ungetService(packageAdminRef);
	}
	private boolean isInstalled(String location) {
		Bundle[] installed = context.getBundles();
		for (int i = 0; i < installed.length; i++) {
			Bundle bundle = installed[i];
			if (location.equalsIgnoreCase(bundle.getLocation()))
				return true;
		}
		return false;
	}
	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);
			if (!DEBUG)
				return;
			DEBUG_CONVERTER = service.getBooleanOption(OPTION_DEBUG_CONVERTER,
					false);
		} finally {
			// we have what we want - release the service
			context.ungetService(reference);
		}
	}
	public static BundleContext getBundleContext() {
		return context;
	}
}