/*******************************************************************************
 *    Copyright (c) 2010, 2011 Eteration A.S. 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
 *           - This code is based on WTP SDK frameworks and Tomcat Server Adapters
 *           org.eclipse.jst.server.core
 *           org.eclipse.jst.server.ui
 *           
 *        Naci Dai and Murat Yener, Eteration A.S.
 *        Kaloyan Raev, SAP AG - integration with OSGi Framework Editor parts
 *******************************************************************************/
package org.eclipse.libra.framework.core;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IDebugEventSetListener;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.libra.framework.editor.core.IOSGiFrameworkAdmin;
import org.eclipse.libra.framework.editor.core.IOSGiFrameworkConsole;
import org.eclipse.libra.framework.editor.core.model.IBundle;
import org.eclipse.libra.framework.editor.integration.admin.osgijmx.LaunchOSGiJMXFrameworkAdmin;
import org.eclipse.libra.framework.editor.integration.console.basic.LaunchBasicOSGiFrameworkConsole;
import org.eclipse.wst.server.core.IModule;
import org.eclipse.wst.server.core.IServer;
import org.eclipse.wst.server.core.internal.IModulePublishHelper;
import org.eclipse.wst.server.core.model.IModuleFile;
import org.eclipse.wst.server.core.model.IModuleResource;
import org.eclipse.wst.server.core.model.IModuleResourceDelta;
import org.eclipse.wst.server.core.model.ServerBehaviourDelegate;


@SuppressWarnings("restriction")
public abstract class OSGIFrameworkInstanceBehaviorDelegate extends ServerBehaviourDelegate implements IModulePublishHelper, IOSGiFrameworkAdmin, IOSGiFrameworkConsole {

	private static final String ATTR_STOP = "stop-server";
	// the thread used to ping the server to check for startup
	protected transient PingThread ping = null;
	protected transient IDebugEventSetListener processListener;
	
	private IOSGiFrameworkAdmin admin = null;
	private IOSGiFrameworkConsole console = null;
	
	public abstract  String[] getFrameworkProgramArguments(boolean starting) ;
	public abstract  String[] getExcludedFrameworkProgramArguments(boolean starting);
	public abstract  String[] getFrameworkVMArguments();
	public abstract  String getFrameworkClass() ;
	
	protected static int getNextToken(String s, int start) {
		int i = start;
		int length = s.length();
		char lookFor = ' ';

		while (i < length) {
			char c = s.charAt(i);
			if (lookFor == c) {
				if (lookFor == '"')
					return i + 1;
				return i;
			}
			if (c == '"')
				lookFor = '"';
			i++;
		}
		return -1;
	}

	/**
	 * Merge the given arguments into the original argument string, replacing
	 * invalid values if they have been changed. Special handling is provided if
	 * the keepActionLast argument is true and the last vmArg is a simple
	 * string. The vmArgs will be merged such that the last vmArg is guaranteed
	 * to be the last argument in the merged string.
	 * 
	 * @param originalArg
	 *            String of original arguments.
	 * @param vmArgs
	 *            Arguments to merge into the original arguments string
	 * @param excludeArgs
	 *            Arguments to exclude from the original arguments string
	 * @param keepActionLast
	 *            If <b>true</b> the vmArguments are assumed to be Framework program
	 *            arguments, the last of which is the action to perform which
	 *            must remain the last argument. This only has an impact if the
	 *            last vmArg is a simple string argument, like
	 *            &quot;start&quot;.
	 * @return merged argument string
	 */
	public static String mergeArguments(final String originalArg, String[] vmArgs,
			String[] excludeArgs, boolean keepActionLast) {
		if (vmArgs == null)
			return originalArg;

		String arg = originalArg;
		if (arg == null)
			arg = "";

		arg = concatArgs(originalArg,  vmArgs, keepActionLast) ;
		arg = excludeArgs(originalArg, excludeArgs);
	
		return arg;
	}
	
	
	private static String concatArgs(String  initialArgs, String[] newArgs, boolean keepLast) {
		if(newArgs == null || newArgs.length <= 0)
			return initialArgs;
		StringBuffer args = new StringBuffer();
		List<String> initArgsList = Arrays.asList(DebugPlugin.parseArguments(initialArgs));
		int i= 0;
		if (initialArgs != null && initialArgs.length() > 0) {
			int last= (keepLast? initArgsList.size()-1 : initArgsList.size() );
			for (i=0; i< last ; i++) {
				if(i != 0)
					args.append(' ');
				args.append(initArgsList.get(i));
			}
		}
		
		for (String anArg: newArgs) {
			if(!initArgsList.contains(anArg)){
				if(i++ != 0)
					args.append(' ');
				args.append(anArg);
			}
		}
		
		if(keepLast && initArgsList.size() >0 ){
			args.append(' ');
			args.append(initArgsList.get(initArgsList.size()-1));
		}
		return args.toString();
	}
	
	private static String excludeArgs(String  initialArgs, String[] excludeArgs) {
		if(excludeArgs == null || excludeArgs.length <= 0)
			return initialArgs;
		StringBuffer args = new StringBuffer();
		List<String> excludeArgsList = Arrays.asList(excludeArgs);
		if (initialArgs != null && initialArgs.length() > 0) {
			String[] initArgsArray = DebugPlugin.parseArguments(initialArgs);
			int i=0;
			for (String anArg : initArgsArray) {
				if (!excludeArgsList.contains(anArg)) {
					if(i++ != 0)
						args.append(' ');
					args.append(anArg);
				}
			}
		}
		return args.toString();
	}

	/**
	 * Replace the current JRE container classpath with the given entry.
	 * 
	 * @param cp
	 * @param entry
	 */
	public static void replaceJREContainer(List<IRuntimeClasspathEntry> cp, IRuntimeClasspathEntry entry) {
		int size = cp.size();
		for (int i = 0; i < size; i++) {
			IRuntimeClasspathEntry entry2 = cp.get(i);
			if (entry2.getPath().uptoSegment(2).isPrefixOf(entry.getPath())) {
				cp.set(i, entry);
				return;
			}
		}

		cp.add(0, entry);
	}

	/**
	 * Merge a single classpath entry into the classpath list.
	 * 
	 * @param cp
	 * @param entry
	 */
	public static void mergeClasspath(List<IRuntimeClasspathEntry> cp, IRuntimeClasspathEntry entry) {
		Iterator<IRuntimeClasspathEntry> iterator = cp.iterator();
		while (iterator.hasNext()) {
			IRuntimeClasspathEntry entry2 = iterator.next();

			if (entry2.getPath().equals(entry.getPath()))
				return;
		}

		cp.add(entry);
	}

	public OSGIFrameworkInstanceBehaviorDelegate() {
		super();
	}

	public void setServerStarted() {
		setServerState(IServer.STATE_STARTED);
	}

	public void stopImpl() {
		if (ping != null) {
			ping.stop();
			ping = null;
		}
		if (processListener != null) {
			DebugPlugin.getDefault().removeDebugEventListener(processListener);
			processListener = null;
		}
		admin = null;
		console = null;
		setServerState(IServer.STATE_STOPPED);
	}

	/**
	 * Cleanly shuts down and terminates the server.
	 * 
	 * @param force
	 *            <code>true</code> to kill the server
	 */
	@Override
	public void stop(boolean force) {
		if (force) {
			terminate();
			return;
		}
		int state = getServer().getServerState();
		// If stopped or stopping, no need to run stop command again
		if (state == IServer.STATE_STOPPED || state == IServer.STATE_STOPPING)
			return;
		else if (state == IServer.STATE_STARTING) {
			terminate();
			return;
		}

		try {
			if (Trace.isTraceEnabled())
				Trace.trace(Trace.FINER, "Stopping OSGi Framework");
			if (state != IServer.STATE_STOPPED)
				setServerState(IServer.STATE_STOPPING);

			// ILaunchConfiguration launchConfig = ((Server)
			// getServer()).getLaunchConfiguration(true, null);
			// ILaunchConfigurationWorkingCopy wc =
			// launchConfig.getWorkingCopy();
			//
			// String args =
			// renderCommandLine(getRuntimeProgramArguments(false)," ");
			// wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS,args);
			// wc.setAttribute("org.eclipse.debug.ui.private", true);
			// wc.setAttribute(ATTR_STOP, "true");
			// wc.launch(ILaunchManager.RUN_MODE, new NullProgressMonitor());
			this.terminate();

		} catch (Exception e) {
			Trace.trace(Trace.SEVERE, "Error stopping OSGi Framework", e);
		}
	}

	/**
	 * Terminates the server.
	 */
	protected void terminate() {
		if (getServer().getServerState() == IServer.STATE_STOPPED)
			return;

		try {
			setServerState(IServer.STATE_STOPPING);
			if (Trace.isTraceEnabled())
				Trace.trace(Trace.FINER, "Killing the OSGi Framework process");
			ILaunch launch = getServer().getLaunch();
			if (launch != null) {
				launch.terminate();
				stopImpl();
			}
		} catch (Exception e) {
			Trace.trace(Trace.SEVERE, "Error killing the process", e);
		}
	}

	@Override
	public IPath getTempDirectory() {
		return super.getTempDirectory(false);
	}

	public IPath getBaseDirectory() {

		IPath confDir = getTempDirectory(true);
		String instancePathStr = getFrameworkInstance().getInstanceDirectory();
		if (instancePathStr != null) {
			IPath instanceDir = new Path(getFrameworkInstance()
					.getInstanceDirectory());
			confDir = instanceDir;
		}

		return confDir;
	}

	@Override
	public void initialize(IProgressMonitor monitor) {
		// do nothing
	}

	public IOSGIFramework getFramework() {
		if (getServer().getRuntime() == null)
			return null;

		return (IOSGIFramework) getServer().getRuntime().loadAdapter(
				IOSGIFramework.class, null);
	}

	public IOSGIFrameworkInstance getFrameworkInstance() {
		return (IOSGIFrameworkInstance) getServer().loadAdapter(
				IOSGIFrameworkInstance.class, null);
	}

	public void addProcessListener(final IProcess newProcess) {
		if (processListener != null || newProcess == null)
			return;

		processListener = new IDebugEventSetListener() {
			public void handleDebugEvents(DebugEvent[] events) {
				if (events != null) {
					int size = events.length;
					for (int i = 0; i < size; i++) {
						if (true
								&& newProcess.equals(events[i].getSource())
								&& events[i].getKind() == DebugEvent.TERMINATE) {
							stopImpl();
						}
					}
				}
			}
		};
		DebugPlugin.getDefault().addDebugEventListener(processListener);
	}

	/**
	 * Setup for starting the server.
	 * 
	 * @param launch
	 *            ILaunch
	 * @param launchMode
	 *            String
	 * @param monitor
	 *            IProgressMonitor
	 * @throws CoreException
	 *             if anything goes wrong
	 */
	public void setupLaunch(ILaunch launch, String launchMode,
			IProgressMonitor monitor) throws CoreException {
		if ("true".equals(launch.getLaunchConfiguration().getAttribute(ATTR_STOP, "false")))
			return;
		if (getFramework() == null)
			throw new CoreException(new Status(IStatus.ERROR, FrameworkCorePlugin.PLUGIN_ID, "Can't launch for OSGi Framework"));

		IStatus status = getFramework().validate();
		if (status != null && status.getSeverity() == IStatus.ERROR)
			throw new CoreException(status);

		setServerRestartState(false);
		setServerState(IServer.STATE_STARTING);
		setMode(launchMode);

		// ping server to check for startup
		try {
			String url = "http://" + getServer().getHost();
			ping = new PingThread(launch, getServer(), url, -1, this);
		} catch (Exception e) {
			Trace.trace(Trace.SEVERE, "Can't ping for OSGi Framework startup.");
		}
	}




	/**
	 * Return a string representation of this object.
	 * 
	 * @return java.lang.String
	 */
	@Override
	public String toString() {
		return "OSGiFrameworkInstance";
	}

	@Override
	public void setupLaunchConfiguration(
			ILaunchConfigurationWorkingCopy workingCopy,
			IProgressMonitor monitor) throws CoreException {
		String existingProgArgs = workingCopy.getAttribute(
				IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS,
				(String) null);
		workingCopy.setAttribute(
				IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS,
				mergeArguments(existingProgArgs,
						getFrameworkProgramArguments(true),
						getExcludedFrameworkProgramArguments(true), true));

		String existingVMArgs = workingCopy.getAttribute(
				IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS,
				(String) null);
		String[] parsedVMArgs = null;
		if (null != existingVMArgs) {
			parsedVMArgs = DebugPlugin.parseArguments(existingVMArgs);
		}
		String[] configVMArgs = getFrameworkVMArguments();

		workingCopy.setAttribute(
				IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS,
				mergeArguments(existingVMArgs, configVMArgs, null, false));

		IOSGIFramework runtime = getFramework();
		IVMInstall vmInstall = runtime.getVMInstall();
		if (vmInstall != null)
			workingCopy.setAttribute(
					IJavaLaunchConfigurationConstants.ATTR_JRE_CONTAINER_PATH,
					JavaRuntime.newJREContainerPath(vmInstall)
							.toPortableString());

		// update classpath
		IRuntimeClasspathEntry[] originalClasspath = JavaRuntime
				.computeUnresolvedRuntimeClasspath(workingCopy);
		int size = originalClasspath.length;
		List<IRuntimeClasspathEntry> oldCp = new ArrayList<IRuntimeClasspathEntry>(originalClasspath.length + 2);
		for (int i = 0; i < size; i++)
			oldCp.add(originalClasspath[i]);

		@SuppressWarnings("unchecked")
		List<IRuntimeClasspathEntry> cp2 = runtime.getFrameworkClasspath(null);
		Iterator<IRuntimeClasspathEntry> iterator = cp2.iterator();
		while (iterator.hasNext()) {
			IRuntimeClasspathEntry entry = iterator
					.next();
			mergeClasspath(oldCp, entry);
		}

		if (vmInstall != null) {
			try {
				String typeId = vmInstall.getVMInstallType().getId();
				replaceJREContainer(oldCp,
						JavaRuntime.newRuntimeContainerClasspathEntry(new Path(
								JavaRuntime.JRE_CONTAINER).append(typeId)
								.append(vmInstall.getName()),
								IRuntimeClasspathEntry.BOOTSTRAP_CLASSES));
			} catch (Exception e) {
				// ignore
			}

			IPath jrePath = new Path(vmInstall.getInstallLocation().getAbsolutePath());
			if (jrePath.toFile().exists()){
				IPath toolsPath = jrePath.append("lib").append("tools.jar");
				if (toolsPath.toFile().exists()) {
					IRuntimeClasspathEntry toolsJar = JavaRuntime
							.newArchiveRuntimeClasspathEntry(toolsPath);
					// Search for index to any existing tools.jar entry
					int toolsIndex;
					for (toolsIndex = 0; toolsIndex < oldCp.size(); toolsIndex++) {
						IRuntimeClasspathEntry entry = oldCp
								.get(toolsIndex);
						if (entry.getType() == IRuntimeClasspathEntry.ARCHIVE
								&& entry.getPath().lastSegment()
										.equals("tools.jar")) {
							break;
						}
					}
					// If existing tools.jar found, replace in case it's
					// different. Otherwise add.
					if (toolsIndex < oldCp.size())
						oldCp.set(toolsIndex, toolsJar);
					else
						mergeClasspath(oldCp, toolsJar);
				}
			}
		}

		iterator = oldCp.iterator();
		List<String> list = new ArrayList<String>();
		while (iterator.hasNext()) {
			IRuntimeClasspathEntry entry = iterator
					.next();
			try {
				list.add(entry.getMemento());
			} catch (Exception e) {
				Trace.trace(Trace.SEVERE, "Could not resolve classpath entry: "
						+ entry, e);
			}
		}

		workingCopy.setAttribute(
				IJavaLaunchConfigurationConstants.ATTR_CLASSPATH, list);
		workingCopy
				.setAttribute(
						IJavaLaunchConfigurationConstants.ATTR_DEFAULT_CLASSPATH,
						false);
	}

	@Override
	protected IModuleResource[] getResources(IModule[] module) {
		return super.getResources(module);
	}

	@Override
	protected IModuleResourceDelta[] getPublishedResourceDelta(IModule[] module) {
		return super.getPublishedResourceDelta(module);
	}

	/**
	 * @see ServerBehaviourDelegate#handleResourceChange()
	 */
	@Override
	public void handleResourceChange() {
		if (getServer().getServerRestartState())
			return;

		List<IModule[]> modules = getAllModules();
		for(IModule[] module: modules) {
			IModuleResourceDelta[] delta = getPublishedResourceDelta(module);
			if (delta == null || delta.length == 0)
				continue;

			if (containsNonResourceChange(delta)) {
				setServerRestartState(true);
				return;
			}
		}
	}

	protected boolean containsNonResourceChange(IModuleResourceDelta[] delta) {
		int size = delta.length;
		for (int i = 0; i < size; i++) {
			IModuleResourceDelta d = delta[i];
			if (d.getModuleRelativePath().segmentCount() == 0) {
				if ("WEB-INF".equals(d.getModuleResource().getName())) {
					return containsNonResourceChange(d.getAffectedChildren());
				}
				continue;
			}
			if (d.getModuleResource() instanceof IModuleFile)
				return true;

			boolean b = containsNonAddChange(d.getAffectedChildren());
			if (b)
				return true;
		}
		return false;
	}

	protected boolean containsNonAddChange(IModuleResourceDelta[] delta) {
		if (delta == null)
			return false;
		int size = delta.length;
		for (int i = 0; i < size; i++) {
			IModuleResourceDelta d = delta[i];
			if (d.getModuleResource() instanceof IModuleFile) {
				if (d.getKind() != IModuleResourceDelta.ADDED)
					return true;
			}

			boolean b = containsNonAddChange(d.getAffectedChildren());
			if (b)
				return true;
		}
		return false;
	}

	/**
	 * Cleans the entire work directory for this server. This involves deleting
	 * all subdirectories of the server's work directory.
	 * 
	 * @param monitor
	 *            a progress monitor
	 * @return results of the clean operation
	 * @throws CoreException
	 */
	public IStatus cleanFrameworkInstanceWorkDir(IProgressMonitor monitor)
			throws CoreException {
		return Status.OK_STATUS;
	}

	public IPath getPublishDirectory(IModule[] module) {
		return getServerDeployDirectory();
	}

	/**
	 * Gets the directory to which modules should be deployed for this server.
	 * 
	 * @return full path to deployment directory for the server
	 */
	public IPath getServerDeployDirectory() {
		return new Path(getFrameworkInstance().getInstanceDirectory());
	}

	/**
	 * Gets the directory to which to deploy a module's web application.
	 * 
	 * @param module
	 *            a module
	 * @return full path to deployment directory for the module
	 */
	public IPath getModuleDeployDirectory(IModule module) {
		return getServerDeployDirectory().append(module.getName());
	}

	public void setModulePublishState2(IModule[] module, int state) {
		setModulePublishState(module, state);
	}

	public Properties loadModulePublishLocations() {
		Properties p = new Properties();
		IPath path = getTempDirectory().append("publish.txt");
		FileInputStream fin = null;
		try {
			fin = new FileInputStream(path.toFile());
			p.load(fin);
		} catch (Exception e) {
			// ignore
		} finally {
			try {
				if (fin!=null) fin.close();
			} catch (Exception ex) {
				// ignore
			}
		}
		return p;
	}

	public void saveModulePublishLocations(Properties p) {
		IPath path = getTempDirectory().append("publish.txt");
		FileOutputStream fout = null;
		try {
			fout = new FileOutputStream(path.toFile());
			p.store(fout, "OSGi Framework publish data");
		} catch (Exception e) {
			// ignore
		} finally {
			try {
				if (fout!=null) fout.close();
			} catch (Exception ex) {
				// ignore
			}
		}
	}
	
	public Map<Long, IBundle> getBundles(IProgressMonitor monitor) throws CoreException {
		return getAdmin().getBundles(monitor);
	}
	
	public void startBundle(long bundleId) throws CoreException {
		getAdmin().startBundle(bundleId);
	}
	
	public void stopBundle(long bundleId) throws CoreException {
		getAdmin().stopBundle(bundleId);
	}
	
	public void refreshBundle(long bundleId) throws CoreException {
		getAdmin().refreshBundle(bundleId);
	}
	
	public void updateBundle(long bundleId) throws CoreException {
		getAdmin().updateBundle(bundleId);
	}
	
	public String executeCommand(String command) throws CoreException {
		return getConsole().executeCommand(command);
	}
	
	private IOSGiFrameworkAdmin getAdmin() throws CoreException {
		if (admin == null) {
			admin = new LaunchOSGiJMXFrameworkAdmin(getLaunch());
		}
		return admin;
	}
	
	private IOSGiFrameworkConsole getConsole() throws CoreException {
		if (console == null) {
			console = new LaunchBasicOSGiFrameworkConsole(getLaunch());
		}
		return console;
	}
	
	private ILaunch getLaunch() throws CoreException {
		IServer server = getServer();
		if (server == null) {
			throw new CoreException(new Status(IStatus.ERROR, FrameworkCorePlugin.PLUGIN_ID, 
					Messages.OSGIFrameworkInstanceBehaviorDelegate_ServerNotInitialized));
		}
		
		ILaunch launch = server.getLaunch();
		if (launch == null) {
			throw new CoreException(new Status(IStatus.ERROR, FrameworkCorePlugin.PLUGIN_ID, 
					Messages.OSGIFrameworkInstanceBehaviorDelegate_ServerNotStarted));
		}
		
		return launch;
	}
	
}