/*******************************************************************************
 * Copyright (c) 2003, 2006 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;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResourceRuleFactory;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.MultiRule;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.eclipse.wst.server.core.IServer;
import org.eclipse.wst.server.core.IServer.IOperationListener;
import org.eclipse.wst.server.core.internal.ServerSchedulingRule;
/**
 * Dialog that prompts a user to delete server(s) and/or server configuration(s).
 */
public class DeleteServerDialog extends MessageDialog {
	protected IServer[] servers;
	protected IFolder[] configs;

	protected List runningServersList;
	protected boolean runningServerCanStop;

	protected Button checkDeleteConfigs;
	protected Button checkDeleteRunning;
	protected Button checkDeleteRunningStop;

	/**
	 * DeleteServerDialog constructor comment.
	 * 
	 * @param parentShell a shell
	 * @param servers an array of servers
	 * @param configs an array of server configurations
	 */
	public DeleteServerDialog(Shell parentShell, IServer[] servers, IFolder[] configs) {
		super(parentShell, Messages.deleteServerDialogTitle, null, null, QUESTION,
				new String[] { IDialogConstants.OK_LABEL, IDialogConstants.CANCEL_LABEL }, 0);
		
		if (servers == null || configs == null)
			throw new IllegalArgumentException();
		
		this.servers = servers;
		this.configs = configs;
		
		runningServersList = new ArrayList();
		for (int i = 0 ; i < servers.length ; ++i) {
			if (servers[i].getServerState() != IServer.STATE_STOPPED)
				runningServersList.add(servers[i]);
			
			if (servers[i].canStop().isOK())
				runningServerCanStop = true;
		}
		
		if (servers.length == 1)
			message = NLS.bind(Messages.deleteServerDialogMessage, servers[0].getName());
		else
			message = NLS.bind(Messages.deleteServerDialogMessageMany, servers.length + "");
	}

	/**
	 * 
	 */
	protected Control createCustomArea(Composite parent) {
		// create a composite with standard margins and spacing
		Composite composite = new Composite(parent, SWT.NONE);
		GridLayout layout = new GridLayout();
		layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
		layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
		layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
		layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
		composite.setLayout(layout);
		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
		composite.setFont(parent.getFont());
		PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, ContextIds.DELETE_SERVER_DIALOG);
		
		if (configs.length > 0) {
			checkDeleteConfigs = new Button(composite, SWT.CHECK);
			checkDeleteConfigs.setText(NLS.bind(Messages.deleteServerDialogLooseConfigurations, configs[0].getName()));
			checkDeleteConfigs.setSelection(true);
		}
		
		// prompt for stopping running servers
		int size = runningServersList.size();
		if (size > 0) {
			checkDeleteRunning = new Button(composite, SWT.CHECK);
			checkDeleteRunning.setText(Messages.deleteServerDialogRunningServer);
			checkDeleteRunning.setSelection(true);
			
			if (runningServerCanStop) {
				checkDeleteRunningStop = new Button(composite, SWT.CHECK);
				checkDeleteRunningStop.setText(Messages.deleteServerDialogRunningServerStop);
				checkDeleteRunningStop.setSelection(true);
				GridData data = new GridData();
				data.horizontalIndent = 15;
				checkDeleteRunningStop.setLayoutData(data);
				
				checkDeleteRunning.addSelectionListener(new SelectionAdapter() {
					public void widgetSelected(SelectionEvent e) {
						checkDeleteRunningStop.setEnabled(checkDeleteRunning.getSelection());
					}
				});
			}
		}
		
		Dialog.applyDialogFont(composite);
		
		return composite;
	}

	protected void buttonPressed(int buttonId) {
		if (buttonId == OK) {
			final boolean checked = (checkDeleteConfigs != null && checkDeleteConfigs.getSelection());
			final boolean deleteRunning = (checkDeleteRunning != null && checkDeleteRunning.getSelection());
			final boolean deleteRunningStop = (checkDeleteRunningStop != null && checkDeleteRunningStop.getSelection());
			
			Job job = new Job(Messages.deleteServerTask) {
				protected IStatus run(IProgressMonitor monitor) {
					if (runningServersList.size() > 0) {
						// stop servers and/or updates servers' list
						prepareForDeletion(deleteRunning, deleteRunningStop);
					}
					
					if (servers.length == 0) {
						// all servers have been deleted from list
						return Status.OK_STATUS;
					}
					try {
						int size = servers.length;
						for (int i = 0; i < size; i++)
							servers[i].delete();
						
						if (checked) {
							size = configs.length;
							for (int i = 0; i < size; i++)
								configs[i].delete(true, true, monitor);
						}
					} catch (Exception e) {
						Trace.trace(Trace.SEVERE, "Error while deleting resources", e);
					}
							
					return Status.OK_STATUS;
				}
			};
			
			// set rule for workspace and servers
			int size = servers.length;
			ISchedulingRule[] rules = new ISchedulingRule[size+1];
			for (int i = 0; i < size; i++)
				rules[i] = new ServerSchedulingRule(servers[i]);
			IResourceRuleFactory ruleFactory = ResourcesPlugin.getWorkspace().getRuleFactory();
			rules[size] = ruleFactory.createRule(ResourcesPlugin.getWorkspace().getRoot());
			job.setRule(MultiRule.combine(rules));
			
			job.schedule();
		}
		super.buttonPressed(buttonId);
	}

	/**
	 * Updates servers' & configs' lists. If <code>deleteRunning</code> is <code>true</code>
	 * 	and a server can't be stopped, it isn't removed.
	 * @param deleteRunning if <code>true</code> running servers will be stopped
	 * 	before being deleted, if <code>false</code> running servers will be removed
	 *    from deletion list.
	 */
	protected void prepareForDeletion(boolean deleteRunning, boolean stopRunning) {
		// converts servers & configs to list to facilitate removal
		List serversList = new LinkedList(Arrays.asList(servers));
		List configsList = new LinkedList(Arrays.asList(configs));
		if (!deleteRunning) {
			// don't delete servers or configurations
			int size = runningServersList.size();
			for (int i = 0; i < size; i++) {
				IServer server = (IServer) runningServersList.get(i);
				serversList.remove(server);
				if (server.getServerConfiguration() != null)
					configsList.remove(server.getServerConfiguration());
			}
		} else {
			if (stopRunning) {
				// stop running servers and wait for them (stop is asynchronous)
				IServer s;
				MultiServerStopListener listener = new MultiServerStopListener();
				int expected = 0;
				Iterator iter = runningServersList.iterator();
				while (iter.hasNext()) {
					s = (IServer) iter.next();
					if (s.canStop().isOK()) {
						++expected;
						s.stop(false, listener);
					} else {
						// server can't be stopped, don't delete it
						serversList.remove(s);
						configsList.remove(s.getServerConfiguration());
					}
				}
				try {
					while (expected != listener.getNumberStopped()) {
						Thread.sleep(100);
					}
				} catch (InterruptedException e) {
					Trace.trace(Trace.WARNING, "Interrupted while waiting for servers stop");
				}
			}
		}
		servers = new IServer[serversList.size()];
		serversList.toArray(servers);
		configs = new IFolder[configsList.size()];
		configsList.toArray(configs);
	}

	/**
	 * Class used to wait all servers stop. Use one instance
	 * for a group of servers and loop to see if the number stopped
	 * equals the number of servers waiting to stop.
	 */
	class MultiServerStopListener implements IOperationListener {
		protected int num; 

		public void done(IStatus result) {
			num++;
		}

		public int getNumberStopped() {
			return num;
		}
	}
}