/*******************************************************************************
 * Copyright (c) 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.core.runtime.adaptor;

import java.io.*;
import java.lang.reflect.Constructor;
import java.net.*;
import java.util.*;
import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
import org.eclipse.osgi.framework.internal.core.OSGi;
import org.osgi.framework.*;
import org.osgi.service.packageadmin.PackageAdmin;
import org.osgi.service.startlevel.StartLevel;
import org.eclipse.osgi.framework.tracker.ServiceTracker;

public class EclipseStarter {

	private static BundleContext context;
	private static String dataLocation = null;
	private static String configLocation = null;

	// command line arguments
	private static final String CONSOLE = "-console"; //$NON-NLS-1$
	private static final String DEBUG = "-debug"; //$NON-NLS-1$
	private static final String DEV = "-dev"; //$NON-NLS-1$
	private static final String WS = "-ws"; //$NON-NLS-1$
	private static final String OS = "-os"; //$NON-NLS-1$
	private static final String ARCH = "-arch"; //$NON-NLS-1$
	private static final String NL = "-nl"; //$NON-NLS-1$	
	private static final String CONFIGURATION = "-configuration"; //$NON-NLS-1$	
	// this is more of an Eclipse argument but this OSGi implementation stores its 
	// metadata alongside Eclipse's.
	private static final String DATA = "-data"; //$NON-NLS-1$

	
	// Constants for configuration location discovery
	private static final String ECLIPSE = "eclipse"; //$NON-NLS-1$
	private static final String PRODUCT_SITE_MARKER = ".eclipseproduct"; //$NON-NLS-1$
	private static final String PRODUCT_SITE_ID = "id"; //$NON-NLS-1$
	private static final String PRODUCT_SITE_VERSION = "version"; //$NON-NLS-1$

	/** string containing the classname of the adaptor to be used in this framework instance */
	protected static String adaptorClassName = "org.eclipse.core.runtime.adaptor.EclipseAdaptor";

	// Console information
	protected static final String consoleClassName = "org.eclipse.osgi.framework.internal.core.FrameworkConsole";
	private static final String CONSOLE_NAME = "OSGi Console";
	private static String consolePort = "";
	private static boolean console = false;
	private static ServiceTracker applicationTracker;

	public static Object run(String[] args,Runnable endSplashHandler) throws Exception {
		processCommandLine(args);
		if (System.getProperty("osgi.bundles") == null)
			System.getProperties().put("osgi.bundles", "org.eclipse.osgi.services_3.0.0@1,org.eclipse.osgi.util_3.0.0@1,org.eclipse.core.runtime.osgi_3.0.0@2,org.eclipse.update.configurator_3.0.0@3,org.eclipse.core.applicationrunner_3.0.0@5");
		setInstanceLocation();
		setConfigurationLocation();
		FrameworkAdaptor adaptor = null;
		adaptor = createAdaptor();
		OSGi osgi = new OSGi(adaptor);
		if (osgi == null) 
			throw new IllegalStateException("OSGi framework could not be started");
		osgi.launch();

		try {
			if (console) 
				startConsole(osgi, new String[0]);
				
			context = osgi.getBundleContext();			
			publishSplashScreen(endSplashHandler);
			
			initializeApplicationTracker();
			loadBundles();
			// TODO determine how long to wait here
			Runnable application = (Runnable)applicationTracker.waitForService(9999999999L);
			applicationTracker.close();
			if (application == null)
				throw new IllegalStateException("Unable to acquire application service");
			application.run();
		} finally {
			Bundle systemBundle = context.getBundle(0);
			if (systemBundle.getState() == Bundle.ACTIVE) {
				final Semaphore semaphore = new Semaphore(0);
				FrameworkListener listener = new FrameworkListener() {
					public void frameworkEvent(FrameworkEvent event) {
						if (event.getType() == FrameworkEvent.STARTLEVEL_CHANGED)
							semaphore.release();
					}
					
				};
				context.addFrameworkListener(listener);
				systemBundle.stop();
				semaphore.acquire();
				context.removeFrameworkListener(listener);
			}
		}
		// TODO for now, if an exception is not thrown from this method, we have to do
		// the System.exit.  In the future we will update startup.jar to do the System.exit all 
		// the time.
		String exitCode = System.getProperty("eclipse.exitcode");
		if (exitCode == null)
			System.exit(0);
		try {
			System.exit(Integer.parseInt(exitCode));
		} catch (NumberFormatException e) {
			System.exit(13);
		}
		return null;
	}

	private static void publishSplashScreen(Runnable endSplashHandler) {
		// InternalPlatform now how to retrieve this later
		Dictionary properties = new Hashtable();
		properties.put("name","splashscreen");
		context.registerService(Runnable.class.getName(),endSplashHandler,properties);		
	}

	private static String searchForBundle(String name, String syspath) {
		String location = "reference:file:"+ syspath +"/"+name;
		try {
			URLConnection result = new URL(location).openConnection();
			result.connect();
			return location;
		} catch (IOException e) {
			int i = location.indexOf('_');
			return i == -1? location : location.substring(0, i);
		}
	}

	private static String[] loadBundles() {
		long startTime = System.currentTimeMillis();
		ServiceReference reference = context.getServiceReference(StartLevel.class.getName());
		StartLevel start = null;
		if (reference != null) 
			start = (StartLevel)context.getService(reference);
		String[] bundles = getArrayFromList(System.getProperty("osgi.bundles"));			

		String syspath = getSysPath();
		Bundle bundle;
		Vector installed = new Vector();
		Vector ignored = new Vector();
		for (int i = 0; i < bundles.length; i++) {
			String name = bundles[i];
			if (name == null)
				continue;
			try {
				int level = -1;
				int index = name.indexOf('@');
				if (index >= 0) {
					String levelString = name.substring(index + 1, name.length());
					level = Integer.parseInt(levelString);
					name = name.substring(0, index);
				}
				String location = searchForBundle(name, syspath);
				if (!isInstalled(location)) {
					bundle = context.installBundle(location);
					if (level >= 0 && start != null)
						start.setBundleStartLevel(bundle, level);
					installed.addElement(bundle);
				} else 
					ignored.addElement(name);			
			} catch (Exception ex) {
				System.err.println("Ignoring " + name);
				ex.printStackTrace();
				ignored.addElement(name);
				continue;
			}
		}
		refreshPackages((Bundle[])installed.toArray(new Bundle[installed.size()]));
			
		Enumeration e = installed.elements();
		while (e.hasMoreElements()) {
			bundle = (Bundle)e.nextElement();
			try {
				bundle.start();				
			} catch (BundleException ex) {
				System.out.println("Error starting " + bundle.getLocation());
				ex.printStackTrace();
			}
		}
		// TODO remove this constant.  At least set it to the max of 6 and the current value...
		start.setStartLevel(6);
		context.ungetService(reference);
		System.out.println("Time (re)start the framework: " + (System.currentTimeMillis() - startTime));
		return (String[])ignored.toArray(new String[ignored.size()]);
	}

	private static 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 Semaphore semaphore = new Semaphore(0);
		FrameworkListener listener = new FrameworkListener() {
			public void frameworkEvent(FrameworkEvent event) {
				if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED)
					semaphore.release();
			}
		};
		context.addFrameworkListener(listener);
		packageAdmin.refreshPackages(bundles);
		semaphore.acquire();
		context.removeFrameworkListener(listener);
		context.ungetService(packageAdminRef);
	}
	
	/**
	 *  Invokes the OSGi Console on another thread
	 *
	 * @param osgi The current OSGi instance for the console to attach to
	 * @param consoleArgs An String array containing commands from the command line
	 * for the console to execute
	 */
	private static void startConsole(OSGi osgi, String[] consoleArgs) {
		try {
			Class consoleClass = Class.forName(consoleClassName);
			Class[] parameterTypes;
			Object[] parameters;
			if (consolePort.length() == 0) {
				parameterTypes = new Class[] { OSGi.class, String[].class };
				parameters = new Object[] { osgi, consoleArgs };
			} else {
				parameterTypes = new Class[] { OSGi.class, int.class, String[].class };
				parameters = new Object[] { osgi, new Integer(consolePort), consoleArgs };
			}
			Constructor constructor = consoleClass.getConstructor(parameterTypes);
			Object console = constructor.newInstance(parameters);
			Thread t = new Thread(((Runnable) console), CONSOLE_NAME);
			t.start();
		} catch (NumberFormatException nfe) {
			System.err.println("Invalid console port: " + consolePort);
		} catch (Exception ex) {
			System.out.println("Failed to find/start: " + CONSOLE_NAME);
		}

	}

	/**
	 *  Creates and returns the adaptor
	 *
	 *  @return a FrameworkAdaptor object
	 */
	private static FrameworkAdaptor createAdaptor() throws Exception {
		Class adaptorClass = Class.forName(adaptorClassName);
		Class[] constructorArgs = new Class[] { String[].class };
		Constructor constructor = adaptorClass.getConstructor(constructorArgs);
		return (FrameworkAdaptor) constructor.newInstance(new Object[] { new String[0] });
	}

	private static String[] processCommandLine(String[] args) throws Exception {
		EnvironmentInfo.allArgs = args;
		int[] configArgs = new int[100];
		configArgs[0] = -1; // need to initialize the first element to something that could not be an index.
		int configArgIndex = 0;
		for (int i = 0; i < args.length; i++) {
			boolean found = false;
			// check for args without parameters (i.e., a flag arg)
	
			// check if development mode should be enabled for the entire platform
			// If this is the last arg or there is a following arg (i.e., arg+1 has a leading -), 
			// simply enable development mode.  Otherwise, assume that that the following arg is
			// actually some additional development time class path entries.  This will be processed below.
			if (args[i].equalsIgnoreCase(DEV) && ((i + 1 == args.length) || ((i + 1 < args.length) && (args[i + 1].startsWith("-"))))) { //$NON-NLS-1$
				System.getProperties().put("osgi.dev", "");
				found = true;
				continue;
			}
	
			// look for the console with no port.  
			if (args[i].equalsIgnoreCase(CONSOLE)) {
				console = true;
				found = true;
				continue;
			}

			if (found) {
				configArgs[configArgIndex++] = i;
				continue;
			}
			// check for args with parameters. If we are at the last argument or if the next one
			// has a '-' as the first character, then we can't have an arg with a parm so continue.
			if (i == args.length - 1 || args[i + 1].startsWith("-")) { //$NON-NLS-1$
				continue;
			}
			String arg = args[++i];
	
			// look for the console and port.  
			if (args[i - 1].equalsIgnoreCase(CONSOLE)) {
				console = true;
				consolePort = arg;
				found = true;
				continue;
			}
	
			// look for the configuraiton location .  
			if (args[i - 1].equalsIgnoreCase(CONFIGURATION)) {
				configLocation = arg;
				continue;
			}
	
			// look for the development mode and class path entries.  
			if (args[i - 1].equalsIgnoreCase(DEV)) {
				System.getProperties().put("osgi.dev", arg);
				found = true;
				continue;
			}
	
			// look for the data location for this instance.  
			if (args[i - 1].equalsIgnoreCase(DATA)) {
				dataLocation = arg;
				continue;
			}
	
			// look for the debug mode and option file location.  
			if (args[i - 1].equalsIgnoreCase(DEBUG)) {
				System.getProperties().put("osgi.debug", arg);
				found = true;
				continue;
			}
	
			// look for the window system.  
			if (args[i - 1].equalsIgnoreCase(WS)) {
				found = true;
				System.getProperties().put("osgi.ws", arg);
			}
	
			// look for the operating system
			if (args[i - 1].equalsIgnoreCase(OS)) {
				found = true;
				System.getProperties().put("osgi.os", arg);
			}
	
			// look for the system architecture
			if (args[i - 1].equalsIgnoreCase(ARCH)) {
				found = true;
				System.getProperties().put("osgi.arch", arg);
			}
	
			// look for the nationality/language
			if (args[i - 1].equalsIgnoreCase(NL)) {
				found = true;
				System.getProperties().put("osgi.nl", arg);
			}
	
			// done checking for args.  Remember where an arg was found 
			if (found) {
				configArgs[configArgIndex++] = i - 1;
				configArgs[configArgIndex++] = i;
			}
		}
	
		// remove all the arguments consumed by this argument parsing
		if (configArgIndex == 0) {
			EnvironmentInfo.frameworkArgs = new String[0];
			EnvironmentInfo.appArgs = args;
			return args;
		}
		EnvironmentInfo.appArgs = new String[args.length - configArgIndex];
		EnvironmentInfo.frameworkArgs = new String[configArgIndex];
		configArgIndex = 0;
		int j = 0;
		int k = 0;
		for (int i = 0; i < args.length; i++) {
			if (i == configArgs[configArgIndex]) {
				EnvironmentInfo.frameworkArgs[k++] = args[i];
				configArgIndex++;
			} else
				EnvironmentInfo.appArgs[j++] = args[i];
		}
		return EnvironmentInfo.appArgs;
	}
	
	/**
	 * Returns the result of converting a list of comma-separated tokens into an array
	 * 
	 * @return the array of string tokens
	 * @param prop the initial comma-separated string
	 */
	private static String[] getArrayFromList(String prop) {
		if (prop == null || prop.trim().equals("")) //$NON-NLS-1$
			return new String[0];
		Vector list = new Vector();
		StringTokenizer tokens = new StringTokenizer(prop, ","); //$NON-NLS-1$
		while (tokens.hasMoreTokens()) {
			String token = tokens.nextToken().trim();
			if (!token.equals("")) //$NON-NLS-1$
				list.addElement(token);
		}
		return list.isEmpty() ? new String[0] : (String[]) list.toArray(new String[list.size()]);
	}

	private static String getSysPath() {
		String result = System.getProperty("osgi.syspath");
		if (result != null) 
			return result;

		URL url = EclipseStarter.class.getProtectionDomain().getCodeSource().getLocation();
		result = url.getFile();
		if (result.endsWith("/"))
			result = result.substring(0, result.length() - 1);
		result = result.substring(0, result.lastIndexOf('/'));
		result = result.substring(0, result.lastIndexOf('/'));
		return result;
	}

	private static void setInstanceLocation() {
		File result = null;
		String location = System.getProperty("osgi.instance.area");
		// if the instance location is not set, predict where the workspace will be and 
		// put the instance area inside the workspace meta area.
		if (location == null) {
			if (dataLocation == null) 
				result = new File(System.getProperty("user.dir"), "workspace");//$NON-NLS-1$ //$NON-NLS-2$
			else
				result = new File(dataLocation);
			result = new File(result, ".metadata/bundles");
		} else {
			result = new File(location);
		}
		System.getProperties().put("osgi.instance.area", result.getAbsolutePath());	
		System.getProperties().put("org.eclipse.osgi.framework.defaultadaptor.bundledir", result.getAbsolutePath());	
	}

	private static void setConfigurationLocation() {
		String location = System.getProperty("osgi.configuration.area");
		if (location != null) {
			configLocation = location;
			if (System.getProperty("osgi.manifest.cache") == null)
				System.getProperties().put("osgi.manifest.cache", configLocation + "/manifests");
			return;
		}
		// -configuration was not specified so compute a configLocation based on the
		// install location.  If it is read/write then use it.  Otherwise use the user.dir
		if (configLocation == null) {
			configLocation = getDefaultStateLocation() + "/.config";
			// TODO handle the case where the install location is read only.  Find out
			// how they do it in the update code and do the same here.
		} else {
			// if -configuration was specified, then interpret the config location from the 
			// value given.  Allow for the specification of a config file (.cfg) or a dir.
			try {
				configLocation = new URL(configLocation).getFile();
			} catch (MalformedURLException e) {
				// TODO do something in the error case
			}
			configLocation = configLocation.replace('\\', '/');
			int index = configLocation.lastIndexOf('/');
			if (configLocation.endsWith(".cfg") || configLocation.endsWith("/")) 
				configLocation = configLocation.substring(0, index);
		} 
		System.getProperties().put("osgi.configuration.area", configLocation);
		if (System.getProperty("osgi.manifest.cache") == null) {
			System.getProperties().put("osgi.manifest.cache", configLocation + "/manifests");
		}
	}

	private static 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 static String getDefaultStateLocation() {
		// 1) We store the config state relative to the 'eclipse' directory if possible
		// 2) If this directory is read-only 
		//    we store the state in <user.home>/.eclipse/<application-id>_<version> where <user.home> 
		//    is unique for each local user, and <application-id> is the one 
		//    defined in .eclipseproduct marker file. If .eclipseproduct does not
		//    exist, use "eclipse" as the application-id.
		
		String installProperty = System.getProperty("eclipse.installURL");
		URL installURL = null;
		try {
			installURL = new URL(installProperty);
		} catch (MalformedURLException e) {
			// do nothgin here since it is basically impossible to get a bogus url 
		}
		File installDir = new File(installURL.getFile());
		if ("file".equals(installURL.getProtocol()) && installDir.canWrite()) { //$NON-NLS-1$
//			if (DEBUG)
//				debug("Using the installation directory."); //$NON-NLS-1$
			return installDir.getAbsolutePath();
		}

		// We can't write in the eclipse install dir so try for some place in the user's home dir
//		if (DEBUG)
//			debug("Using the user.home location."); //$NON-NLS-1$
		String appName = "." + ECLIPSE; //$NON-NLS-1$
		File eclipseProduct = new File(installDir, PRODUCT_SITE_MARKER );
		if (eclipseProduct.exists()) {
			Properties props = new Properties();
			try {
				props.load(new FileInputStream(eclipseProduct));
				String appId = props.getProperty(PRODUCT_SITE_ID);
				if (appId == null || appId.trim().length() == 0)
					appId = ECLIPSE;
				String appVersion = props.getProperty(PRODUCT_SITE_VERSION);
				if (appVersion == null || appVersion.trim().length() == 0)
					appVersion = ""; //$NON-NLS-1$
				appName += File.separator + appId + "_" + appVersion; //$NON-NLS-1$
			} catch (IOException e) {
				// Do nothing if we get an exception.  We will default to a standard location 
				// in the user's home dir.
			}
		}

		String userHome = System.getProperty("user.home"); //$NON-NLS-1$
		File configDir = new File(userHome, appName);
		configDir.mkdirs();
		return configDir.getAbsolutePath();
	}
	
	private static void initializeApplicationTracker() {
		Filter filter = null;
		try {
			filter = context.createFilter("(&(objectClass=java.lang.Runnable)(eclipse.application=*))");
		} catch (InvalidSyntaxException e) {
			// ignore this.  It should never happen as we have tested the above format.
			e.printStackTrace();
		}
		applicationTracker = new ServiceTracker(context, filter, null);
		applicationTracker.open();
	}
}


