/*******************************************************************************
 * Copyright (c) 2000, 2004 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.jst.ws.internal.common;

import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.List;
import java.util.Vector;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.jem.util.logger.proxy.Logger;
import org.eclipse.jst.j2ee.internal.J2EEVersionConstants;
import org.eclipse.jst.j2ee.internal.servertarget.IServerTargetConstants;
import org.eclipse.wst.command.internal.env.core.common.MessageUtils;
import org.eclipse.wst.command.internal.env.core.common.StatusUtils;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.environment.IEnvironment;
import org.eclipse.wst.server.core.IModule;
import org.eclipse.wst.server.core.IRuntime;
import org.eclipse.wst.server.core.IRuntimeType;
import org.eclipse.wst.server.core.IServer;
import org.eclipse.wst.server.core.IServerType;
import org.eclipse.wst.server.core.IServerWorkingCopy;
import org.eclipse.wst.server.core.ServerCore;
import org.eclipse.wst.server.core.ServerUtil;
import org.eclipse.wst.server.core.model.IURLProvider;

/**
 * This class contains useful methods for working with Server plugin functions
 */
public final class ServerUtils {

	private MessageUtils msgUtils_;

	private Hashtable serverIdToLabel_;

	private Hashtable serverLabelToId_;

	private static ServerUtils instance_;

	public static ServerUtils getInstance() {
		if (instance_ == null) {
			instance_ = new ServerUtils();
		}
		return instance_;

	}

	public ServerUtils() {
		String pluginId = "org.eclipse.jst.ws";
		msgUtils_ = new MessageUtils(pluginId + ".plugin", this);
	}

	// Gets the Server labels given the server factory id
	public void getServerLabelsAndIds() {
		serverIdToLabel_ = new Hashtable();
		serverLabelToId_ = new Hashtable();
		IServerType[] serverTypes = ServerCore.getServerTypes();
		for (int idx = 0; idx < serverTypes.length; idx++) {

			IServerType serverType = (IServerType) serverTypes[idx];

			String id = serverType.getId();
			String serverLabel = serverType.getName();
			if (!(id == null) && !(serverLabel == null)) {
				serverIdToLabel_.put(id, serverLabel);
				serverLabelToId_.put(serverLabel, id);
			}
		}
	}

	public String getServerLabelForId(String factoryId) {
		if (serverIdToLabel_ == null)
			this.getServerLabelsAndIds();
		return (String) serverIdToLabel_.get(factoryId);
	}

	public String getServerIdForLabel(String factoryLabel) {
		if (serverLabelToId_ == null)
			this.getServerLabelsAndIds();
		return (String) serverLabelToId_.get(factoryLabel);
	}

	public IStatus modifyModules(IEnvironment env, IServer server,
			IModule module, boolean add, IProgressMonitor monitor) {

		IServerWorkingCopy wc = null;
		IStatus status = Status.OK_STATUS;
    
		try {

			if (module == null || !module.getProject().exists()) {
				return status;
			}

			// check if module is a true Java project
			if (module instanceof IModule) {
				IModule pm = (IModule) module;
				if (pm != null) {
					IProject project = pm.getProject();
					if (project == null
							|| ResourceUtils.isTrueJavaProject(project)) {
						return status;
					}
				}
			}

			wc = server.createWorkingCopy();
			if (wc != null) {
//				Object x = server.getAdapter(IRunningActionServer.class);
//				if (x != null && x instanceof IRunningActionServer) {
//					int state = server.getServerState();
//					if (state == IServer.STATE_STOPPED
//							|| state == IServer.STATE_UNKNOWN) {
//						String mode = ILaunchManager.RUN_MODE;
//						server.synchronousStart(mode, monitor);
//					}
//				}

				List list = Arrays.asList(server.getModules());
				if (add) {
					if (!list.contains(module)) {
						ServerUtil.modifyModules(wc, new IModule[] { module },
								new IModule[0], monitor);
					}
				} else { // removes module
					if (list.contains(module)) {
						ServerUtil.modifyModules(wc, new IModule[0],
								new IModule[] { module }, monitor);
					}
				}
			} else {
				// handle case of Null WC; non-issue for now
			}
		} 
    catch (CoreException exc ) 
    {
			status = StatusUtils.errorStatus( msgUtils_.getMessage("MSG_ERROR_SERVER"), exc );
			env.getStatusHandler().reportError(status);
			return status;
		} finally {
			if (wc != null) {
				// Always saveAll and release the serverWorkingCopy
				try 
        {
					wc.saveAll(true, monitor);
				} 
        catch (CoreException exc ) 
        {
					status = StatusUtils.errorStatus( msgUtils_.getMessage("MSG_ERROR_SERVER"), exc );
					env.getStatusHandler().reportError(status);
					return status;
				}
			}
		}
		return status;
	}

	public static IServer getServerForModule(IModule module, String serverTypeId, 
								IServer server, boolean create, IProgressMonitor monitor) {
		if (server != null)
			return server;
		else
			return getServerForModule(module, serverTypeId, create, monitor);
	}

	public static IServer getServerForModule(IModule module,
			String serverTypeId, boolean create, IProgressMonitor monitor) {
		try {

			IServer[] servers = ServerUtil.getServersByModule(module, monitor);

			if (servers != null && servers.length > 0) {
				if (serverTypeId == null || serverTypeId.length() == 0)
					return servers[0]; // WSAD v4 behavior

				for (int i = 0; i < servers.length; i++) {
					if (servers[i].getServerType().getId().equalsIgnoreCase(
							serverTypeId))
						return servers[i];
				}
			}

			return createServer(module, serverTypeId, monitor);

		} catch (Exception e) {
			return null;
		}
	}

	public static IServer getServerForModule(IModule module) {
		try {
			IServer[] servers = ServerUtil.getServersByModule(module, null);
			return ((servers != null && servers.length > 0) ? servers[0] : null);
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 
	 * @param env
	 * @param module
	 * @param serverTypeId
	 * @param monitor
	 * @return
	 * 
	 * @deprecated
	 */
	public IServer createServer(IEnvironment env, IModule module,
			String serverTypeId, IProgressMonitor monitor) {
		IServerWorkingCopy serverWC = null;
		IServer server = null;
		try {
			IServerType serverType = ServerCore.findServerType(serverTypeId);
			serverWC = serverType.createServer(serverTypeId, null, monitor);
			try {
				if (serverWC != null) {
					server = serverWC.saveAll(true, monitor);
				}
			} catch (CoreException ce) 
      {
				IStatus status = StatusUtils.errorStatus( msgUtils_.getMessage("MSG_ERROR_SERVER"), ce);
				env.getStatusHandler().reportError(status);
				return null;
			}

			if (server != null) {

//				Object x = server.getAdapter(IRunningActionServer.class);
//				if (x != null && x instanceof IRunningActionServer) {
//					int state = server.getServerState();
//					if (state == IServer.STATE_STOPPED
//							|| state == IServer.STATE_UNKNOWN) {
//						String mode = ILaunchManager.RUN_MODE;
//						server.synchronousStart(mode, monitor);
//					}
//				}

				if (module != null && module.getProject().exists()) {
					IModule[] parentModules = server.getRootModules(module,
							monitor);
					if (parentModules != null && parentModules.length != 0) {
						module = (IModule) parentModules[0];
					}
					serverWC.modifyModules(new IModule[] { module },
							new IModule[0], monitor);
				}

			}

			return server;
		} 
    catch (Exception e) 
    {
			IStatus status = StatusUtils.errorStatus( msgUtils_.getMessage("MSG_ERROR_SERVER"), e);
			env.getStatusHandler().reportError(status);
			return null;
		} finally {
			try {
				if (serverWC != null) {
					serverWC.saveAll(true, monitor);
				}
			} catch (CoreException ce) {
				IStatus status = StatusUtils.errorStatus( msgUtils_.getMessage("MSG_ERROR_SERVER"), ce);
				env.getStatusHandler().reportError(status);
				return null;
			}
		}
	}

	/**
	 * createServer This creates a server but does not report errors. @param
	 * module 
	 * @param serverTypeId 
	 * @param monitor progress monitor 
	 * @return IServer returns null if unsuccessful
	 * 
	 * @deprecated
	 */
	public static IServer createServer(IModule module, String serverTypeId,
			IProgressMonitor monitor) {
		IServerWorkingCopy serverWC = null;
		IServer server = null;
		try {
			IServerType serverType = ServerCore.findServerType(serverTypeId);
			serverWC = serverType.createServer(serverTypeId, null, monitor);

			try {
				if (serverWC != null) {
					server = serverWC.saveAll(true, monitor);
				}
			} catch (CoreException ce) {
				return null;
			}

			if (server != null) {

//				Object x = server.getAdapter(IRunningActionServer.class);
//				if (x != null && x instanceof IRunningActionServer) {
//					int state = server.getServerState();
//					if (state == IServer.STATE_STOPPED
//							|| state == IServer.STATE_UNKNOWN) {
//						String mode = ILaunchManager.RUN_MODE;
//						server.synchronousStart(mode, monitor);
//					}
//				}
				if (module != null) {
					IModule[] parentModules = server.getRootModules(module,
							monitor);
					if (parentModules != null && parentModules.length != 0) {
						module = (IModule) parentModules[0];
					}
					serverWC.modifyModules(new IModule[] { module },
							new IModule[0], monitor);
				}

			}

			return server;
		} catch (Exception e) {
			return null;
		} finally {
			try {
				if (serverWC != null) {
					serverWC.saveAll(true, monitor);
				}
			} catch (CoreException ce) {
				return null;
				// handler core exception
			}
		}
	}

	public static String[] getServerTypeIdsByModule(IVirtualComponent component) {
		IProject project = component.getProject();
		String[] serverIds = null;

		if (project != null) {
			IServer[] servers = ServerUtil.getServersByModule(getModule(project), null);
			if (servers != null) {
				serverIds = new String[servers.length];

				for (int index = 0; index < servers.length; index++) {
					serverIds[index] = servers[index].getId();

				}
			}
		}

		if (serverIds == null) {
			serverIds = new String[0];
		}

		return serverIds;
	}

	/**
	 * @param project
	 * @return
	 * @deprecated should be using getServerTypeIdsByModule( IVirtualComponent )
	 */
	public static String[] getServerTypeIdsByModule(IProject project) {
		Vector serverIds = new Vector();
		if (project != null) {
			IServer[] servers = ServerUtil.getServersByModule(ResourceUtils
					.getModule(project), null);
			if (servers != null && servers.length > 0) {
				for (int i = 0; i < servers.length; i++) {
					serverIds.add(servers[i].getId());
				}
			}
		}
		return (String[]) serverIds.toArray(new String[serverIds.size()]);
	}

	public static IModule getModule(IProject project) {
	return ServerUtil.getModule(project);
}
	
// Workaround for 113621
//public static IModule getModule(IProject project) {
//	IModule[] modules = ServerUtil.getModules(project);
//	if (modules!=null && modules.length!=0) {
//		return modules[0];
//	}
//	return null;
//}
  
	/**
	 * Returns the URL string corresponding to the web server module root of the
	 * component in a server instance or null if the project has no Web nature
	 * or has no association to a server instance.
	 * 
	 * @param project
	 *            The project.
	 * @return The web server module root URL or null if the project has no Web
	 *         nature or has no association to a server instance.
	 */
	public static String getWebComponentURL(IProject project, String serverFactoryId) {
		String webProjectURL = null;
		IModule module = getModule(project);
		if (module != null) {
			IServer serverInstance = getServerForModule(module);
			if (serverInstance != null) {
				IURLProvider urlProvider = (IURLProvider) serverInstance.loadAdapter(IURLProvider.class, null);
				if (urlProvider!=null) {
					URL url = urlProvider.getModuleRootURL(module);
					if (url != null) {
						String s = url.toString();
						webProjectURL = (s.endsWith("/") ? s.substring(0, s.length() - 1) : s);
					}
				}
			}
			else {
				//IRuntime projectTarget = ServerCore.getProjectProperties(project).getRuntimeTarget();
                IServerType serverType = ServerCore.findServerType(serverFactoryId);               
				if (serverType!=null)
				{
					try {
                        //Choose a Runtime which is not a stub
                        IRuntime nonStubRuntime = null;
                        IRuntime[] runtimes = ServerUtil.getRuntimes(null, null);
                        String serverRuntimeTypeId = serverType.getRuntimeType().getId();
                        for (int i = 0; i < runtimes.length; i++) {
                            IRuntime runtime = runtimes[i];
                            String thisRuntimeTypeId = runtime.getRuntimeType().getId();
                            if (thisRuntimeTypeId.equals(serverRuntimeTypeId) && !runtime.isStub()) {
                                //Found an appropriate IRuntime that is not a stub
                                nonStubRuntime = runtime;
                                break;
                            }
                        }
                        
                        if (nonStubRuntime != null)
                        {
					      IServerWorkingCopy serverWC = serverType.createServer(null, null, nonStubRuntime, null);
						  IURLProvider urlProvider = (IURLProvider) serverWC.loadAdapter(IURLProvider.class, null);
						  if (urlProvider!=null) {
						     URL url = urlProvider.getModuleRootURL(module);							
							 if (url != null) {
								String s = url.toString();
								webProjectURL = (s.endsWith("/") ? s.substring(0, s.length() - 1) : s);
							 }				
						  }
                        }

					} catch(CoreException ce){
                        Logger.getLogger().log(ce);
					}
					
				}
			}
		}
		return webProjectURL;
	}

	/**
	 * Returns the URL string corresponding to the web server module root of the
	 * project in a server instance or null if the project has no Web nature or
	 * has no association to a server instance.
	 * 
	 * @param project
	 *            The project.
	 * @return The web server module root URL or null if the project has no Web
	 *         nature or has no association to a server instance.
	 */
	public static String getWebComponentURL(IProject project,
			String serverFactoryId, IServer server) {

		String webProjectURL = null;
		IModule module = getModule(project);
		if (module != null) {
			IServer serverInstance = ServerUtils.getServerForModule(module, serverFactoryId, server, true, new NullProgressMonitor());
			if (serverInstance != null) {
                IURLProvider urlProvider = (IURLProvider) serverInstance.loadAdapter(IURLProvider.class, null);
                if (urlProvider!=null) {
                    URL url = urlProvider.getModuleRootURL(module);              
					if (url != null) {
					  String s = url.toString();
					  webProjectURL = (s.endsWith("/") ? s.substring(0, s.length() - 1) : s);
                    }
				}
			}
		}
		return webProjectURL;
	}

	public static String getEncodedWebComponentURL(IProject project, String serverFactoryId) {
		String url = getWebComponentURL(project, serverFactoryId);
		if (url != null) {
			int index = url.lastIndexOf('/');
			if (index != -1) {
				StringBuffer encodedURL = new StringBuffer();
				encodedURL.append(url.substring(0, index + 1));
				try {
					String ctxtRoot = URLEncoder.encode(url.substring(index + 1, url.length()), "UTF-8");
					int plusIndex = ctxtRoot.indexOf('+');
					while (plusIndex != -1) {
						StringBuffer sb = new StringBuffer();
						sb.append(ctxtRoot.substring(0, plusIndex));
						sb.append("%20");
						sb.append(ctxtRoot.substring(plusIndex + 1, ctxtRoot
							.length()));
						ctxtRoot = sb.toString();
						plusIndex = ctxtRoot.indexOf('+');
					}
					encodedURL.append(ctxtRoot);
				}catch (IOException io){
					//handler exception
				}				
				url = encodedURL.toString();
			}
		}
		return url;
	}	

	public static IServer getDefaultExistingServer(IVirtualComponent component) {
		IProject project = component.getProject();
		IModule module = getModule(project);
		IServer preferredServer = ServerCore.getDefaultServer(module);
		if (preferredServer != null)
			return preferredServer;
		
		IServer[] configuredServers = ServerUtil.getServersByModule(module,
				null);

		if (configuredServers != null && configuredServers.length > 0) {
			preferredServer = configuredServers[0];
		} else {
			IServer[] nonConfiguredServers = ServerUtil
					.getAvailableServersForModule(module, false, null);

			if (nonConfiguredServers != null
					&& nonConfiguredServers.length > 0) {
				preferredServer = nonConfiguredServers[0];
			}
		}

		return preferredServer;
	}

	/**
	 * @param project
	 * @return
	 * @deprecated should be using getDefaultExistingServer( IVirtualComponent )
	 */
	public static IServer getDefaultExistingServer(IProject project) {
    
      IModule module = ServerUtil.getModule(project);
      IServer preferredServer = null;
      preferredServer = ServerCore.getDefaultServer(module);
		
// Workaround for 113621
//		IModule[] modules = ServerUtil.getModules(project);
//      IServer preferredServer = null;
//      if (modules.length > 0){
//        preferredServer = ServerCore.getDefaultServer(modules[0]);
//      }
  
		if (preferredServer != null)
			return preferredServer;

		IServer[] configuredServers = ServerUtil.getServersByModule(
				ResourceUtils.getModule(project), null);
		if (configuredServers != null && configuredServers.length > 0) {
			return configuredServers[0];
		}

		IServer[] nonConfiguredServers = ServerUtil
				.getAvailableServersForModule(ResourceUtils.getModule(project),
						false, null);
		if (nonConfiguredServers != null && nonConfiguredServers.length > 0) {
			return nonConfiguredServers[0];
		}
		return null;
	}

	/*
	 * @param moduleType - ad defined in IServerTargetConstants (i.e. EAR_TYPE,
	 * WEB_TYPE, etc.) @param j2eeVersion String representation of the int
	 * values in J2EEVersionConstants i.e. "12" or "13" or "14" @return String
	 * the id of the server target - to be used in project creation operations.
	 */
	public static String getServerTargetIdFromFactoryId(String serverFactoryId,
			String moduleType, String j2eeVersion) {
		IServerType serverType = ServerCore.findServerType(serverFactoryId);
		if (serverType == null)
			return null;

		String serverRuntimeTypeId = serverType.getRuntimeType().getId();

		String stJ2EEVersion = ServerUtils.getServerTargetJ2EEVersion(j2eeVersion);
        List runtimes = Arrays.asList(ServerUtil.getRuntimes(moduleType, stJ2EEVersion));    
		for (int i = 0; i < runtimes.size(); i++) {
			IRuntime runtime = (IRuntime) runtimes.get(i);
			String thisRuntimeTypeId = runtime.getRuntimeType().getId();
			if (thisRuntimeTypeId.equals(serverRuntimeTypeId) && !runtime.isStub()) {
				return runtime.getId();
			}
		}

		return null;
	}

	/*
	 * @param serverFactoryId the server's factory id @returns the runtime type
	 * id given the server's factory id. Returns a blank String if the no
	 * ServerType exists for the given factory id.
	 */
	public static String getRuntimeTargetIdFromFactoryId(String serverFactoryId) {
		IServerType serverType = ServerCore.findServerType(serverFactoryId);
		if (serverType != null) {
			String serverRuntimeId = serverType.getRuntimeType().getId();
			return serverRuntimeId;
		} else
			return "";
	}
	
	public static String getFactoryIdFromRuntimeTargetId(String runtimeTargetId){
		IServerType[] serverTypes = ServerCore.getServerTypes();
		for (int i=0;i<serverTypes.length;i++) {
			IRuntimeType runtimeTyp = serverTypes[i].getRuntimeType();
			if (runtimeTyp!=null){
				if (runtimeTyp.getId().equals(runtimeTargetId))
					return serverTypes[i].getId();
			}
		}
		return "";
		
	}
	

	/*
	 * @param serverFactoryId the server's factory id @returns the server type
	 * id given the server's factory id. Returns a blank String if the no
	 * ServerType exists for the given factory id.
	 */
	public static String getServerTypeIdFromFactoryId(String serverFactoryId) {
		IServerType serverType = ServerCore.findServerType(serverFactoryId);
		if (serverType != null) {
			String serverTypeId = serverType.getId();
			return serverTypeId;
		} else
			return "";
	}

	/*
	 * @param j2eeVersion String representation of the int values in
	 * J2EEVersionConstants i.e. "12" or "13" or "14"
	 */
	public static boolean isTargetValidForEAR(String runtimeTargetId,
			String j2eeVersion) {
		if (runtimeTargetId == null)
			return false;

		String earModuleType = IServerTargetConstants.EAR_TYPE;
		String stJ2EEVersion = ServerUtils.getServerTargetJ2EEVersion(j2eeVersion);
        List runtimes = Arrays.asList(ServerUtil.getRuntimes(earModuleType, stJ2EEVersion));
		for (int i = 0; i < runtimes.size(); i++) {
			IRuntime runtime = (IRuntime) runtimes.get(i);
			String thisId = runtime.getRuntimeType().getId();
			if (thisId.equals(runtimeTargetId))
				return true;
		}

		return false;
	}

	/*
	 * @param j2eeVersion String representation of the int values in
	 * J2EEVersionConstants i.e. "12" or "13" or "14" @param the project type
	 * from IServerTargetConstants
	 */
	public static boolean isTargetValidForProjectType(String runtimeTargetId,
			String j2eeVersion, String projectType) {
		if (runtimeTargetId == null)
			return false;

		if (projectType == null || projectType.length() == 0)
			return false;

		String stJ2EEVersion = ServerUtils.getServerTargetJ2EEVersion(j2eeVersion);
        List runtimes = Arrays.asList(ServerUtil.getRuntimes(projectType, stJ2EEVersion));    
		for (int i = 0; i < runtimes.size(); i++) {
			IRuntime runtime = (IRuntime) runtimes.get(i);
			String thisId = runtime.getRuntimeType().getId();
			if (thisId.equals(runtimeTargetId))
				return true;
		}

		return false;
	}

	public static String getServerTargetJ2EEVersion(String j2eeVersion) {

		if (j2eeVersion == null || j2eeVersion.length() == 0)
			return null;

		int j2eeVersionInt = Integer.parseInt(j2eeVersion);
		switch (j2eeVersionInt) {
		case (J2EEVersionConstants.J2EE_1_2_ID):
			return IServerTargetConstants.J2EE_12;
		case (J2EEVersionConstants.J2EE_1_3_ID):
			return IServerTargetConstants.J2EE_13;
		case (J2EEVersionConstants.J2EE_1_4_ID):
			return IServerTargetConstants.J2EE_14;
		default:
			return null;
		}
	}
	
	//Converts a module type from J2EEUtils to a module type like
	//the one in IServerTargetConstants.
	public static String getServerTargetModuleType(int moduleType)
	{
		switch (moduleType)
    {
    case J2EEUtils.WEB :
      return IServerTargetConstants.WEB_TYPE;
    case J2EEUtils.EJB :
      return IServerTargetConstants.EJB_TYPE;
    case J2EEUtils.APPCLIENT :
      return IServerTargetConstants.APP_CLIENT_TYPE;
    case J2EEUtils.EAR :
      return IServerTargetConstants.EAR_TYPE;
    default:
      return null;
      
    }      			
	}
}
