/*******************************************************************************
 * Copyright (c) 2003, 2018 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.wst.server.ui.internal.wizard.page;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.fieldassist.*;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.help.IWorkbenchHelpSystem;
import org.eclipse.wst.server.core.*;
import org.eclipse.wst.server.core.internal.*;
import org.eclipse.wst.server.core.util.SocketUtil;
import org.eclipse.wst.server.discovery.Discovery;
import org.eclipse.wst.server.discovery.ErrorMessage;
import org.eclipse.wst.server.ui.AbstractUIControl;
import org.eclipse.wst.server.ui.AbstractUIControl.IUIControlListener;
import org.eclipse.wst.server.ui.AbstractUIControl.UIControlEntry;
import org.eclipse.wst.server.ui.internal.*;
import org.eclipse.wst.server.ui.internal.Messages;
import org.eclipse.wst.server.ui.internal.Trace;
import org.eclipse.wst.server.ui.internal.viewers.ServerTypeComposite;
import org.eclipse.wst.server.ui.internal.wizard.TaskWizard;
import org.eclipse.wst.server.ui.internal.wizard.WizardTaskUtil;
import org.eclipse.wst.server.ui.internal.wizard.fragment.LicenseWizardFragment;
import org.eclipse.wst.server.ui.internal.wizard.page.HostnameComposite.IHostnameSelectionListener;
import org.eclipse.wst.server.ui.wizard.ServerCreationWizardPageExtension;
import org.eclipse.wst.server.ui.wizard.WizardFragment;

/**
 * Wizard page used to create a server and configuration at the same time.
 */
public class NewManualServerComposite extends Composite implements IUIControlListener {
	public interface ServerSelectionListener {
		public void serverSelected(IServerAttributes server);
		public void runtimeSelected(IRuntime runtime);
	}

	public interface IWizardHandle2 {
		public void run(boolean fork, boolean cancelable, IRunnableWithProgress runnable) throws InterruptedException, InvocationTargetException;
		public void update();
		public void setMessage(String newMessage, int newType);
	}
	protected IWizardHandle2 wizard;

	protected ServerTypeComposite serverTypeComposite;

	protected Label runtimeLabel;
	protected Combo runtimeCombo;
	protected Link configureRuntimes;
	protected Link addRuntime;
	protected IRuntime[] runtimes;
	protected IRuntime newRuntime;

	protected Label serverNameLabel;
	protected Text serverName;
	protected String defaultServerName;
	protected boolean serverNameModified;
	protected boolean updatingServerName;
	protected ToolBarManager serverNameToolBar;

	protected IRuntime runtime;
	protected IServerWorkingCopy server;
	protected ServerSelectionListener listener;

	protected String host;

	protected IModuleType moduleType;
	protected IModule module;
	protected String serverTypeId;
	protected boolean includeIncompatible;
	
	protected HostnameComposite manualHostComp;
	IHostnameSelectionListener hostnameListener;
	protected Label hostnameLabel;
	protected Text hostname;
	protected ControlDecoration hostnameDecoration;
	protected FieldDecoration fd;

	protected ServerCreationCache cache = new ServerCreationCache();
	
	private IServerType oldServerType;
	
	HostnameChangedAction hostnameChangeAction;
	Timer timer = null;
	
	private boolean canSupportModule=true;

	// These variables deal with caching server name checks
	private boolean isServerNameInUse=false;
	private String cacheServerNameCheck="";
	
	private HashMap<String,IStatus> serverTypeCriticalFailure = new HashMap<String, IStatus>();
	
	/**
	 * Creates a new server and server configuration.  If the initial
	 * resource selection contains exactly one container resource then it will be
	 * used as the default container resource.
	 *
	 * @param parent a parent composite
	 * @param wizard a wizard handle
	 * @param moduleType a module type
	 * @param module an optional module
	 * @param serverTypeId a server type id, or null
	 * @param includeIncompatible true to include incompatible servers that support similar module types
	 * @param listener a server selection listener
	 */
	public NewManualServerComposite(Composite parent, IWizardHandle2 wizard, IModuleType moduleType, IModule module, String serverTypeId, boolean includeIncompatible, ServerSelectionListener listener) {
		super(parent, SWT.NONE);
		this.wizard = wizard;
		this.listener = listener;
		
		this.moduleType = moduleType;
		this.module = module;
		this.serverTypeId = serverTypeId;
		this.includeIncompatible = includeIncompatible;
		
		createControl();
		wizard.setMessage("", IMessageProvider.ERROR); //$NON-NLS-1$
	}

	/**
	 * Returns this page's initial visual components.
	 */
	protected void createControl() {
		// top level group
		GridLayout layout = new GridLayout();
		layout.numColumns = 3;
		layout.horizontalSpacing = SWTUtil.convertHorizontalDLUsToPixels(this, 4);
		layout.verticalSpacing = SWTUtil.convertVerticalDLUsToPixels(this, 4);
		layout.marginWidth = 0;
		layout.marginHeight = 0;
		setLayout(layout);

		this.setFont(getParent().getFont());
		IWorkbenchHelpSystem whs = PlatformUI.getWorkbench().getHelpSystem();
		whs.setHelp(this, ContextIds.NEW_SERVER_WIZARD);
		
		List<ServerCreationWizardPageExtension> pageExtensionLst = ServerUIPlugin.getServerCreationWizardPageExtensions();
		// Add the page modifier top section UI. 
		for (ServerCreationWizardPageExtension curPageExtension : pageExtensionLst) {
			curPageExtension.createControl(ServerCreationWizardPageExtension.UI_POSITION.TOP, this);
			curPageExtension.setUIControlListener(this);
		}
		
		serverTypeComposite = new ServerTypeComposite(this, moduleType, serverTypeId, new ServerTypeComposite.ServerTypeSelectionListener() {
			public void serverTypeSelected(IServerType type2) {
				handleTypeSelection(type2);
				//WizardUtil.defaultSelect(parent, CreateServerWizardPage.this);
			}
		});
		serverTypeComposite.setIncludeIncompatibleVersions(includeIncompatible);
		GridData data = new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL);
		data.horizontalSpan = 3;
		data.minimumHeight = 150;
		serverTypeComposite.setLayoutData(data);
		whs.setHelp(serverTypeComposite, ContextIds.NEW_SERVER_TYPE);
		
		// Add the page modifier middle section UI. 
		for (ServerCreationWizardPageExtension curPageExtension : pageExtensionLst) {
			curPageExtension.createControl(ServerCreationWizardPageExtension.UI_POSITION.MIDDLE, this);
		}
		
		hostnameListener = 	new IHostnameSelectionListener() {
			public void hostnameSelected(String selectedHostname) {
				setHost(selectedHostname);
			}
	    };		
		hostnameLabel = new Label(this, SWT.NONE);
		hostnameLabel.setText(Messages.hostname);
		hostname = new Text(this, SWT.SINGLE | SWT.BORDER | SWT.CANCEL);
		hostname.setText(HostnameComposite.LOCALHOST);
		hostnameDecoration = new ControlDecoration(hostname, SWT.TOP | SWT.LEAD);
		
		GridData data2 = new GridData(GridData.HORIZONTAL_ALIGN_FILL );
		hostname.setLayoutData(data2);
		new Label(this, SWT.NONE);
		
		hostname.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				setHostnameChangeTimer(hostname.getText());
			}
		});
		
		FieldDecorationRegistry registry = FieldDecorationRegistry.getDefault();
		fd = registry.getFieldDecoration(FieldDecorationRegistry.DEC_CONTENT_PROPOSAL);
		hostnameDecoration.setImage(fd.getImage());
		hostnameDecoration.setDescriptionText(fd.getDescription());
		
		hostname.addFocusListener(new FocusListener() {
			public void focusGained(FocusEvent e) {
				hostnameDecoration.show();
			}

			public void focusLost(FocusEvent e) {
				hostnameDecoration.hide();
			}
		});
		
		List<String> hosts = ServerUIPlugin.getPreferences().getHostnames();
		String[] hosts2 = hosts.toArray(new String[hosts.size()]);
		new AutoCompleteField(hostname, new TextContentAdapter(), hosts2);
		
		serverNameLabel = new Label(this, SWT.NONE);
		serverNameLabel.setText(Messages.serverName);
		
		serverName = new Text(this, SWT.SINGLE | SWT.BORDER | SWT.CANCEL);
		data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
		if ((serverName.getStyle() & SWT.CANCEL) != 0)
			data.horizontalSpan = 2;
		serverName.setLayoutData(data);
		
		if (server != null)
			serverName.setText(server.getName());
		
		serverName.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				if (updatingServerName)
					return;
				
				String name = serverName.getText();
								
				IServerType selectedServerType = serverTypeComposite.getSelectedServerType();
				if (!validate(selectedServerType)) {
					// Do not set the server name if it is invalid
					return;			
				}
				
				if (server != null) {
					server.setName(name);
					String base = serverName.getText().trim();
					if( ServerPlugin.isIdInUse(server, base) ) {
						server.setAttribute("id", generateUniqueId(base));
					}
					IRuntime runtime2 = server.getRuntime();
					if (runtime2 != null && runtime2 instanceof IRuntimeWorkingCopy) {
						IRuntimeWorkingCopy rwc = (IRuntimeWorkingCopy) runtime2;
						rwc.setName(name);
					}
				}
				
				if (serverNameModified)
					return;
				
				serverNameModified = true;
				if (serverNameToolBar != null)
					serverNameToolBar.getControl().setVisible(true);
			}
		});
		
		if ((serverName.getStyle() & SWT.CANCEL) == 0) {
			serverNameToolBar = new ToolBarManager(SWT.FLAT | SWT.HORIZONTAL);
			serverNameToolBar.createControl(this);
			
			IAction resetDefaultAction = new Action("", IAction.AS_PUSH_BUTTON) {//$NON-NLS-1$
				public void run() {
					((ServerWorkingCopy)server).setDefaults(null);
					serverName.setText(server.getName());
					serverNameModified = false;
					if (serverNameToolBar != null)
						serverNameToolBar.getControl().setVisible(false);
				}
			};
			
			resetDefaultAction.setToolTipText(Messages.serverNameDefault);
			resetDefaultAction.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_ETOOL_RESET_DEFAULT));
			resetDefaultAction.setDisabledImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_DTOOL_RESET_DEFAULT));
			
			serverNameToolBar.add(resetDefaultAction);
			serverNameToolBar.update(false);
			serverNameToolBar.getControl().setVisible(false);
		}
		
		runtimeLabel = new Label(this, SWT.NONE);
		runtimeLabel.setText(Messages.wizNewServerRuntime);
		
		runtimeCombo = new Combo(this, SWT.READ_ONLY);
		runtimeCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		runtimeCombo.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent e) {
				try {
					setRuntime(runtimes[runtimeCombo.getSelectionIndex()]);
				} catch (Exception ex) {
					// ignore
				}
			}
			public void widgetDefaultSelected(SelectionEvent e) {
				widgetSelected(e);
			}
		});
		
		addRuntime = new Link(this, SWT.NONE);
		addRuntime.setText("<a>" + Messages.addRuntime + "</a>");
		addRuntime.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
		addRuntime.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				IServerType serverType = serverTypeComposite.getSelectedServerType();
				showRuntimeWizard(serverType);
			}
		});
		
		configureRuntimes = new Link(this, SWT.NONE);
		configureRuntimes.setText("<a>" + Messages.configureRuntimes + "</a>");
		data = new GridData(GridData.HORIZONTAL_ALIGN_END);
		data.horizontalSpan = 3;
		configureRuntimes.setLayoutData(data);
		configureRuntimes.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				if (showPreferencePage()) {
					runtime = null;
					IServerType serverType = serverTypeComposite.getSelectedServerType();
					updateRuntimeCombo(serverType);
				}
			}
		});
		
		// Add the page modifier bottom section UI. 
		for (ServerCreationWizardPageExtension curPageExtension : pageExtensionLst) {
			curPageExtension.createControl(ServerCreationWizardPageExtension.UI_POSITION.BOTTOM, this);
		}
		
		Dialog.applyDialogFont(this);
	}

	String generateUniqueId(String base) {
		// generate a temporary unique id
		long time = System.currentTimeMillis();
		String toTest = new StringBuilder(base).append("_").append(time).toString();
		int num = 1;
		while(ServerPlugin.isIdInUse(server, toTest) ) {
			toTest = new StringBuilder(base).append("_").append(time).append("_").append(num++).toString();
		}
		return toTest;
	}
	
	protected boolean showPreferencePage() {
		String id = "org.eclipse.wst.server.ui.preferencePage";
		String id2 = "org.eclipse.wst.server.ui.runtime.preferencePage";
		final PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(getShell(), id2, new String[] { id, id2 }, null);
		return (dialog.open() == Window.OK);
	}

	protected int showRuntimeWizard(IServerType serverType) {
		WizardFragment fragment = null;
		TaskModel taskModel = new TaskModel();
		IRuntimeType runtimeType = serverType.getRuntimeType();
		final WizardFragment fragment2 = ServerUIPlugin.getWizardFragment(runtimeType.getId());
		if (fragment2 == null)
			return Window.CANCEL;
		
		try {
			IRuntimeWorkingCopy runtimeWorkingCopy = runtimeType.createRuntime(null, null);
			taskModel.putObject(TaskModel.TASK_RUNTIME, runtimeWorkingCopy);
		} catch (CoreException ce) {
			if (Trace.SEVERE) {
				Trace.trace(Trace.STRING_SEVERE, "Error creating runtime", ce);
			}
			return Window.CANCEL;
		}
		fragment = new WizardFragment() {
			protected void createChildFragments(List<WizardFragment> list) {
				list.add(fragment2);
				list.add(WizardTaskUtil.SaveRuntimeFragment);
			}
		};
		TaskWizard wizard2 = new TaskWizard(Messages.wizNewRuntimeWizardTitle, fragment, taskModel);
		wizard2.setForcePreviousAndNextButtons(true);
		WizardDialog dialog = new WizardDialog(getShell(), wizard2);
		int returnValue = dialog.open();
		if (returnValue != Window.CANCEL) {
			updateRuntimeCombo(serverType);
			IRuntime rt = (IRuntime)taskModel.getObject(TaskModel.TASK_RUNTIME);
			if (rt != null && rt.getName() != null && runtimeCombo.indexOf(rt.getName()) != -1) {
				setRuntime(rt);
				runtimeCombo.select(runtimeCombo.indexOf(rt.getName()));
			}
		}
		return returnValue;
	}

	public String getControlStringValue(String controlId) {
		if (controlId != null && AbstractUIControl.PROP_HOSTNAME.equals(controlId)) {
			return host;
		}	
		return null;
	}
	
	public void setHost(String host) {
		this.host = host;
		if (serverTypeComposite == null)
			return;
		
		IServerType selectedServerType = serverTypeComposite.getSelectedServerType();
		handleHostnameChange(selectedServerType);
	}
	
	protected void handleHostnameChange(IServerType serverType) {
		wizard.setMessage(null, IMessageProvider.NONE);
		if (serverType instanceof ServerTypeProxy)
			return;
		if (!validate(serverType)) {
			return;// Host name validation failed, so there is no need to continue handling hostname change event			
		}
		loadServerImpl(serverType);
		
		if (serverName != null && !serverNameModified) {
			updatingServerName = true;
			if (server == null)
				serverName.setText("");
			else
				serverName.setText(server.getName());
			updatingServerName = false;
		}
		
		updateRuntimeCombo(serverType);
		if (serverName != null) {
			if (server == null) {
				serverName.setEditable(false);
				serverNameToolBar.getControl().setVisible(false);
			} else {
				serverName.setEditable(true);
				serverNameToolBar.getControl().setVisible(serverNameModified);
			}
		}
	}

	/**
	 * Validates the server's host name<br/>
	 * @param selectedServerType
	 * @return The results of validation: <br/>
	 * <b>false</b> in case when the selected server type does not support remote host and the field "hostname" is not recognized as localhost one.  This method will also return false on an invalid server type.<br/> 
	 * <b>true</b> in any other case   
	 */
	protected boolean checkHostAndServerType(IServerType selectedServerType){
		if(selectedServerType == null){
			return false;
		}
		if (selectedServerType instanceof ServerTypeProxy)
			return true;
		boolean supportsRemote = selectedServerType.supportsRemoteHosts();
		if (hostname.getText().trim().length() == 0){
			wizard.setMessage(NLS.bind(Messages.wizEmptyHostName, new Object[0]), IMessageProvider.ERROR);
			return false;
		}
		if(!supportsRemote && !SocketUtil.isLocalhost(hostname.getText())) {
			wizard.setMessage(NLS.bind(Messages.wizCheckRemoteSupport, new Object[0]), IMessageProvider.ERROR);
			return false;
		}

		return true;
	}
	
	protected boolean checkServerName(){		
		if (isServerNameInUse()){
			wizard.setMessage(Messages.errorDuplicateServerName, IMessageProvider.ERROR);
			return false;			
		}
		return true;
	}
	
	protected boolean validate(IServerType selectedServerType){
		wizard.setMessage(null, IMessageProvider.NONE);
		boolean ret = (checkHostAndServerType(selectedServerType) & checkServerName());
		if( selectedServerType != null && serverTypeCriticalFailure.get(selectedServerType.getId()) != null ) {
			IStatus stat = serverTypeCriticalFailure.get(selectedServerType.getId());
			int msgProviderSev = stat.getSeverity();
			if( msgProviderSev == IStatus.ERROR)
				msgProviderSev = IMessageProvider.ERROR;
			wizard.setMessage(stat.getMessage(), msgProviderSev);
		}
		return ret;
	}
	
	/**
	 * Load a server of the given type.
	 */
	protected void loadServerImpl(IServerType serverType) {
		server = null;
		
		if (serverType == null)
			return;
		
		boolean isLocalhost = SocketUtil.isLocalhost(host);
		
		server = cache.getCachedServer(serverType, isLocalhost);
		if (server != null) {
			server.setHost(host);
			((ServerWorkingCopy)server).newServerDetailsChanged(null);
			runtime = server.getRuntime();
			listener.runtimeSelected(runtime);
			fireServerWorkingCopyChanged();
			return;
		}
		
		try {
			// try to create runtime first
			IRuntime run = null;
			if (serverType.requiresRuntime()) {
				runtime = null;
				updateRuntimes(serverType, isLocalhost);
				run = getDefaultRuntime();
			}
			server = cache.createServer(serverType, run, isLocalhost, null);
			if (server != null) {
				server.setHost(host);
				
				if (serverType.requiresRuntime() && server.getRuntime() == null) {
					runtime = null;
					updateRuntimes(serverType, isLocalhost);
					setRuntime(getDefaultRuntime());
					
					if (server.getServerType() != null && server.getServerType().hasServerConfiguration() && !runtime.getLocation().isEmpty())
						((ServerWorkingCopy)server).importRuntimeConfiguration(runtime, null);
				}
				
				((ServerWorkingCopy)server).setDefaults(null);
				fireServerWorkingCopyChanged();
			}
		} catch (CoreException ce) {
			if (Trace.SEVERE) {
				Trace.trace(Trace.STRING_SEVERE, "Error creating server", ce);
			}
			server = null;
			runtime = null;
			serverTypeCriticalFailure.put(serverType.getId(), new Status(IStatus.ERROR, ServerUIPlugin.PLUGIN_ID, ce.getLocalizedMessage(), ce));
			wizard.setMessage(ce.getLocalizedMessage(), IMessageProvider.ERROR);
			return; // Return to preserve this error message for clarity
		}
			
		if (server == null) {
			serverTypeCriticalFailure.put(serverType.getId(), new Status(IStatus.ERROR, ServerUIPlugin.PLUGIN_ID, Messages.wizErrorServerCreationError, null));
			wizard.setMessage(Messages.wizErrorServerCreationError, IMessageProvider.ERROR);
		}
	}

	/**
	 * Pick the first non-stub runtime first. Otherwise, just pick the first runtime.
	 * 
	 * @return the default runtime
	 */
	protected IRuntime getDefaultRuntime() {
		if (runtimes == null || runtimes.length == 0)
			return null;
		
		if (runtimes != null) {
			int size = runtimes.length;
			for (int i = 0; i < size; i++) {
				if (!runtimes[i].isStub())
					return runtimes[i];
			}
		}
		return runtimes[0];
	}

	protected void updateRuntimes(IServerType serverType, boolean isLocalhost) {
		if (serverType == null)
			return;
		
		IRuntimeType runtimeType = serverType.getRuntimeType();
		runtimes = ServerUIPlugin.getRuntimes(runtimeType);
		newRuntime = null;
		
		if (runtimes != null) {
			List<IRuntime> runtimes2 = new ArrayList<IRuntime>();
			int size = runtimes.length;
			for (int i = 0; i < size; i++) {
				IRuntime runtime2 = runtimes[i];
				if ((isLocalhost || !runtime2.isStub()) && (runtime2.validate(new NullProgressMonitor()).getSeverity() < IStatus.ERROR))
					runtimes2.add(runtime2);
			}
			runtimes = new IRuntime[runtimes2.size()];
			runtimes2.toArray(runtimes);
			if (runtimes.length > 0)
				return;
		}
		
		// create a new runtime
		try {
			IRuntimeWorkingCopy runtimeWC = runtimeType.createRuntime(null, null);
			runtimes = new IRuntime[1];
			runtimes[0] = runtimeWC;
			newRuntime = runtimeWC;
		} catch (Exception e) {
			if (Trace.SEVERE) {
				Trace.trace(Trace.STRING_SEVERE, "Couldn't create runtime", e);
			}
		}
	}

	protected void updateRuntimeCombo(IServerType serverType) {
		if (serverType == null || !serverType.requiresRuntime() || server == null) {
			if (runtimeLabel != null) {
				runtimeLabel.setEnabled(false);
				runtimeCombo.setItems(new String[0]);
				runtimeCombo.setEnabled(false);
				runtimeLabel.setVisible(false);
				runtimeCombo.setVisible(false);
				configureRuntimes.setEnabled(false);
				configureRuntimes.setVisible(false);
				addRuntime.setEnabled(false);
				addRuntime.setVisible(false);
			}
			runtimes = new IRuntime[0];
			setRuntime(null);
			return;
		}
		
		updateRuntimes(serverType, !SocketUtil.isLocalhost(server.getHost()));
		
		int size = runtimes.length;
		String[] items = new String[size];
		for (int i = 0; i < size; i++) {
			if (runtimes[i].equals(newRuntime))
				items[i] = Messages.wizNewServerRuntimeCreate;
			else
				items[i] = runtimes[i].getName();
		}
		
		if (runtime == null)
			setRuntime(getDefaultRuntime());
		
		if (runtimeCombo != null) {
			runtimeCombo.setItems(items);
			if (runtimes.length > 0) {
				int sel = -1;
				for (int i = 0; i < size; i++) {
					if (runtimes[i].equals(runtime))
						sel = i;
				}
				if (sel < 0) {
					sel = 0;
				}
				
				runtimeCombo.select(sel);
				setRuntime(runtimes[sel]);
			}
			
			IRuntimeType runtimeType = serverType.getRuntimeType();
			boolean showRuntime = ServerUIPlugin.getRuntimes(runtimeType).length >=1;
			runtimeCombo.setEnabled(showRuntime);
			runtimeLabel.setEnabled(showRuntime);
			configureRuntimes.setEnabled(showRuntime);
			addRuntime.setEnabled(showRuntime);
			runtimeLabel.setVisible(showRuntime);
			runtimeCombo.setVisible(showRuntime);
			configureRuntimes.setVisible(showRuntime);
			addRuntime.setVisible(showRuntime);
		}
	}

	protected void setRuntime(IRuntime runtime2) {
		runtime = runtime2;
		if (server != null) {
			server.setRuntime(runtime);
			((ServerWorkingCopy)server).newServerDetailsChanged(null);
			if (!serverNameModified) {
				updatingServerName = true;
				serverName.setText(server.getName());
				updatingServerName = false;
			}
			else {
				server.setName(serverName.getText());
			}
			// Validate if selected module is supported with the selected runtime
			wizard.setMessage(null, IMessageProvider.NONE);
			if( module!=null ){
				canSupportModule=true;
				IStatus status = NewServerComposite.isSupportedModule(server, module);
				if (status != null) {
					if (status.getSeverity() == IStatus.ERROR){
						wizard.setMessage(status.getMessage(), IMessageProvider.ERROR);
						canSupportModule=false;
					}
					else if (status.getSeverity() == IStatus.WARNING)
						wizard.setMessage(status.getMessage(), IMessageProvider.WARNING);
					else if (status.getSeverity() == IStatus.INFO)
						wizard.setMessage(status.getMessage(), IMessageProvider.INFORMATION);
				}
			}
		}
		listener.runtimeSelected(runtime);

	}
	
	protected void fireServerWorkingCopyChanged() {
		List<ServerCreationWizardPageExtension> pageExtensionLst = ServerUIPlugin.getServerCreationWizardPageExtensions();
		// Add the page modifier top section UI. 
		for (ServerCreationWizardPageExtension curPageExtension : pageExtensionLst) {
			curPageExtension.setServerWorkingCopy(getServer());
		}
	}

	boolean canProceed = true;
	public boolean canProceed(){
		return canProceed;
	}
	
	public boolean refreshExtension(){
		if (!(oldServerType instanceof ServerTypeProxy))
			return true;
		final ServerTypeProxy finalServerType = (ServerTypeProxy)oldServerType;
		try {
			wizard.run(true, true, new IRunnableWithProgress() {
				public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
					ErrorMessage errorMsg = Discovery.refreshExtension(finalServerType.getExtension(), finalServerType.getURI(), monitor);
					if (errorMsg != null){
						final ErrorMessage errorMsgFinal = errorMsg;
						Display.getDefault().asyncExec(new Runnable() {
							public void run() {
								canProceed = false;
								wizard.setMessage(errorMsgFinal.getErrorTitle(), IMessageProvider.ERROR);
								WizardFragment fragment2 = ServerUIPlugin.getWizardFragment(finalServerType.getId());
								if (fragment2 != null){
									TaskModel taskModel = fragment2.getTaskModel();
									taskModel.putObject(LicenseWizardFragment.LICENSE, errorMsgFinal.getErrorDescription());
									taskModel.putObject(LicenseWizardFragment.LICENSE_ERROR, new Integer(IMessageProvider.ERROR));
								}
								wizard.update();
							}
						});
					}
					else{
						WizardFragment fragment2 = ServerUIPlugin.getWizardFragment(finalServerType.getId());
						if (fragment2 != null){
							TaskModel taskModel = fragment2.getTaskModel();
							taskModel.putObject(LicenseWizardFragment.LICENSE, Discovery.getLicenseText(finalServerType.getExtension()));
							taskModel.putObject(LicenseWizardFragment.LICENSE_ERROR, new Integer(IMessageProvider.NONE));
						}
					}
				}
			});
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		return true;
	}
	
	protected boolean showDownloadableServerWizard(ServerTypeProxy serverType, IProgressMonitor monitor) {
		Display.getDefault().asyncExec(new Runnable() {
			public void run() {
				wizard.setMessage(Messages.downLoadableAdapterDescription, IMessageProvider.INFORMATION);
			}
		});
		
		WizardFragment fragment2 = ServerUIPlugin.getWizardFragment(serverType.getId());
		if (fragment2 == null)
			return false;
		TaskModel taskModel = fragment2.getTaskModel();
		if (taskModel == null)
			taskModel = new TaskModel();
		taskModel.putObject(TaskModel.TASK_EXTENSION, serverType.getExtension());
		taskModel.putObject(TaskModel.TASK_RUNTIME, serverType.getRuntimeType());
		taskModel.putObject(TaskModel.TASK_SERVER, serverType);
		fragment2.setTaskModel(taskModel);
		return true;
	}
	
	boolean success ;
	/**
	 * Handle the server type selection.
	 */
	protected void handleTypeSelection(IServerType serverType) {
		canProceed = true;
	//	wizard.setMessage(null, IMessageProvider.NONE);
		if (serverType instanceof ServerTypeProxy){
			hostname.setVisible(false);
			serverNameLabel.setVisible(false);
			serverName.setVisible(false);
			hostnameLabel.setVisible(false);
			runtimeLabel.setVisible(false);
			runtimeCombo.setVisible(false);
			configureRuntimes.setVisible(false);
			addRuntime.setVisible(false);
			hostnameDecoration.setImage(null);
			hostnameDecoration.setDescriptionText(null);
			final ServerTypeProxy serverTypeFinal = (ServerTypeProxy)serverType;
			success = false;
			ServerTypeProxy serverProxy = (ServerTypeProxy)serverType;
			RuntimeTypeProxy runtimeProxy = (RuntimeTypeProxy)serverProxy.getRuntimeType();
			runtime = new RuntimeProxy(runtimeProxy);
			server = new ServerWorkingCopy(serverProxy.getId(), null, runtime,serverProxy );
			
			fireServerWorkingCopyChanged();
			listener.serverSelected(server);
			// Fire the property change event. 
			List<ServerCreationWizardPageExtension> pageExtensionLst = ServerUIPlugin.getServerCreationWizardPageExtensions();
			for (ServerCreationWizardPageExtension curPageExtension : pageExtensionLst) {
				curPageExtension.handlePropertyChanged(new PropertyChangeEvent(this, AbstractUIControl.PROP_SERVER_TYPE, oldServerType, serverType));
			}
			wizard.update();
			try {
				wizard.run(true, true, new IRunnableWithProgress() {
					
					public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
						success = showDownloadableServerWizard(serverTypeFinal, monitor);
				}
				});
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			}
			
			if (success){
				// Update the old server type value.
				oldServerType = serverTypeFinal;
				
			}
			wizard.update();

			return;
		}

		if (serverType != null){
			// Update the old server type value.
			hostname.setVisible(true);
			serverNameLabel.setVisible(true);
			serverName.setVisible(true);
			hostnameLabel.setVisible(true);
			if (serverType.requiresRuntime() && server != null
					&& ServerUIPlugin.getRuntimes(serverType.getRuntimeType()).length >= 1) {
				runtimeLabel.setVisible(true);
				runtimeCombo.setVisible(true);
				configureRuntimes.setVisible(true);
				addRuntime.setVisible(true);
			}
			hostnameDecoration.setImage(fd.getImage());
			hostnameDecoration.setDescriptionText(fd.getDescription());
		}
		boolean wrong = false;
		if (serverType != null && moduleType != null) {
			IRuntimeType runtimeType = serverType.getRuntimeType();
			// dummy module type means matches all module types
			boolean dummyModule = moduleType.getId() == null && moduleType.getVersion() == null;
			if (!dummyModule && !ServerUtil.isSupportedModule(runtimeType.getModuleTypes(), moduleType)) {
				serverType = null;
				wrong = true;
				//wizard.setMessage("Not the right spec level2", IMessageProvider.ERROR);
			}
		}
		
		if (wrong) {
			server = null;
			runtime = null;
			wizard.setMessage(NLS.bind(Messages.errorVersionLevel, new Object[] { moduleType.getName(), moduleType.getVersion() }), IMessageProvider.ERROR);
		} else if (serverType == null) {
			server = null;
			runtime = null;
			wizard.setMessage("", IMessageProvider.ERROR); //$NON-NLS-1$
		} else {
			//wizard.setMessage(null, IMessageProvider.NONE);
			loadServerImpl(serverType);
			if (server != null && module != null) {
				IStatus status = NewServerComposite.isSupportedModule(server, module);
				if (status != null) {
					if (status.getSeverity() == IStatus.ERROR)
						wizard.setMessage(status.getMessage(), IMessageProvider.ERROR);
					else if (status.getSeverity() == IStatus.WARNING)
						wizard.setMessage(status.getMessage(), IMessageProvider.WARNING);
					else if (status.getSeverity() == IStatus.INFO)
						wizard.setMessage(status.getMessage(), IMessageProvider.INFORMATION);
				}
			}
		}
		
		if (serverName != null && !serverNameModified) {
			updatingServerName = true;
			if (server == null)
				serverName.setText("");
			else
				serverName.setText(server.getName());
			updatingServerName = false;
		}
		
		updateRuntimeCombo(serverType);
		if (serverName != null) {
			if (server == null) {
				serverName.setEditable(false);
				serverNameToolBar.getControl().setVisible(false);
			} else {
				serverName.setEditable(true);
				serverNameToolBar.getControl().setVisible(serverNameModified);
			}
		}
		
		if (hostname != null && server != null) {
			hostname.setText(server.getHost());
		}
		listener.serverSelected(server);
		// Fire the property change event. 
		List<ServerCreationWizardPageExtension> pageExtensionLst = ServerUIPlugin.getServerCreationWizardPageExtensions();
		for (ServerCreationWizardPageExtension curPageExtension : pageExtensionLst) {
			curPageExtension.handlePropertyChanged(new PropertyChangeEvent(this, AbstractUIControl.PROP_SERVER_TYPE, oldServerType, serverType));
		}
		// Update the old server type value.
		oldServerType = serverType;

		validate(serverType);
		wizard.update();
	}

	public void setVisible(boolean visible) {
		super.setVisible(visible);
	
		if (visible) {
			/*if (defaultServerFactory != null) {
				tree.setSelection(new TreeItem[] { defaultServerFactory });
				tree.showItem(tree.getItems()[0]);
			}*/
			// force the focus to initially validate the fields
			handleTypeSelection(null);
		}
		
		Control[] c = getChildren();
		if (c != null) {
			int size = c.length;
			for (int i = 0; i < size; i++)
				if (c[i] != null && c[i] instanceof ServerTypeComposite)
					c[i].setVisible(visible);
		}
		if (visible)
			handleTypeSelection(serverTypeComposite.getSelectedServerType());
	}

	public void refresh() {
		serverTypeComposite.refresh();
	}

	public IRuntime getRuntime() {
		return runtime;
	}

	public IServerWorkingCopy getServer() {
		return server;
	}

	protected void hostnameChanged(String newHost) {
		if (newHost == null)
			return;
		/*
		 * Bug 349434, with the fix in Timer.runTimer, the chance that a new 
		 * host name is the same as the host name will be very rare. In some  
		 * cases, it still needs to go through processes such as loadServerImpl. 
		 * It doesn't worth to handle it differently. Therefore, we are not checking 
		 * for the same host name in here.
		 */

		host = newHost;
		hostnameListener.hostnameSelected(host);
	}

	public void handleUIControlMapChanged(Map<String, UIControlEntry> controlMap) {
		if (controlMap == null) {
			return;
		}
		
		for (String curControlId : controlMap.keySet()) {
			if (AbstractUIControl.PROP_HOSTNAME.equals(curControlId)) {
				UIControlEntry curControlEntry = controlMap.get(curControlId);
				if (hostnameLabel != null)
					hostnameLabel.setEnabled(curControlEntry.isEnabled());
				
				if (hostname != null){
					if (curControlEntry.getNewTextValue() != null)
						hostname.setText(curControlEntry.getNewTextValue());
					
					hostname.setEnabled(curControlEntry.isEnabled());
				}
				
				if (hostnameDecoration != null){
					if(curControlEntry.isEnabled())
						hostnameDecoration.show();
					else
						hostnameDecoration.hide();
				}
			}
		}
	}

	public String getCurrentHostname() {
		if (hostname != null)
			return hostname.getText();
		return null;
	}

	public boolean canSupportModule() {
		return canSupportModule;
	}

	void setHostnameChangeTimer(String hostName) {
		if (hostnameChangeAction == null) {
			hostnameChangeAction = new HostnameChangedAction(hostName);
		} else {
			hostnameChangeAction.setHostName(hostName);
		}

		if (timer == null) {
			timer = new Timer(300, hostnameChangeAction);
		}
		/*
		 * Kick off the timer and then call setMessage if the Timer wasn't
		 * previously running because we want to trigger the isComplete on the page
		 * so that it stops the user from proceeding to the next page while the
		 * timer is running.
		 */
		if (!timer.isRunning()) {
			timer.runTimer();
			wizard.setMessage(null, IMessageProvider.NONE);
		} else {
			timer.runTimer();
		}
	}

	public boolean isTimerRunning() {
		if (timer == null) {
			return false;
		}
		return timer.isRunning();
	}

	public boolean isTimerScheduled() {
		if (timer == null) {
			return false;
		}
		return timer.isScheduled();
	}

	/**
	 * Disposes the timer when the wizard is disposed.
	 */
	public void dispose() {
		if (timer != null) {
			timer.dispose();
			timer = null;
		}
	}

	private class HostnameChangedAction implements ActionListener {

		String hostName;

		public HostnameChangedAction(String name) {
			hostName = name;
		}

		public void actionPerformed(ActionEvent a) {
			Display.getDefault().asyncExec(new Runnable() {
				public void run() {
						hostnameChanged(hostName);
				}
			});
		}

		void setHostName(String host) {
			hostName = host;
		}
	}
	
	/**
	 * Determines if the server name is in use. The server name that is checked
	 * is cached to increase performance on multiple calls. 
	 * 
	 * @return true if name is in use, false otherwise
	 */
	public boolean isServerNameInUse(){
		String myServerName="";
		if (serverName != null){
			myServerName = serverName.getText().trim();
			// If the server name is equal to the cached server name, then return the
			// previously cached value. If the server name is not equal to the cached
			// server name, check to see if the name is in use
			if (!cacheServerNameCheck.equals(myServerName)){
				cacheServerNameCheck = myServerName;
				isServerNameInUse = ServerPlugin.isNameOnlyInUse(server, serverName.getText().trim());				
			}
			return isServerNameInUse;			
		}

		// If the widget is null, return false
		return false;
	}	
	
}