/*******************************************************************************
* Copyright (c) 2007 IONA Technologies PLC
* 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:
*     IONA Technologies PLC - initial API and implementation
*******************************************************************************/
package org.eclipse.stp.sc.common.internal.preferences;

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

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.window.Window;
import org.eclipse.stp.sc.common.internal.model.RuntimeCore;
import org.eclipse.stp.sc.common.internal.viewers.StpRuntimeCheckComposite;
import org.eclipse.stp.sc.common.internal.viewers.StpRuntimeComposite;
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.DirectoryDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.PlatformUI;
import org.eclipse.wst.server.core.IRuntime;
import org.eclipse.wst.server.core.IRuntimeWorkingCopy;
import org.eclipse.wst.server.core.IServer;
import org.eclipse.wst.server.core.ServerCore;
import org.eclipse.wst.server.core.internal.IRuntimeLocator;
import org.eclipse.wst.server.core.internal.ServerPlugin;
import org.eclipse.wst.server.ui.internal.ContextIds;
import org.eclipse.wst.server.ui.internal.EclipseUtil;
import org.eclipse.wst.server.ui.internal.Messages;
import org.eclipse.wst.server.ui.internal.SWTUtil;
import org.eclipse.wst.server.ui.internal.Trace;



/**
 * runtime preference page. just reuse wst page for now
 * will change later to show only stp related runtime
 * This will only list stp related runtime information
 * @author jma
 *
 */
public class RuntimePreferencePage extends
		org.eclipse.wst.server.ui.internal.RuntimePreferencePage {
	
	/**
	 * Create the preference options.
	 *
	 * @param parent org.eclipse.swt.widgets.Composite
	 * @return org.eclipse.swt.widgets.Control
	 */
	protected Control createContents(Composite parent) {
		initializeDialogUnits(parent);
		PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, ContextIds.PREF_GENERAL);
		
		Composite composite = new Composite(parent, SWT.NONE);
		GridLayout layout = new GridLayout();
		layout.horizontalSpacing = convertHorizontalDLUsToPixels(4);
		layout.verticalSpacing = convertVerticalDLUsToPixels(3);
		layout.marginWidth = 0;
		layout.marginHeight = 0;
		layout.numColumns = 2;
		composite.setLayout(layout);
		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL);
		composite.setLayoutData(data);
		
		Label label = new Label(composite, SWT.WRAP);
		data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
		data.horizontalSpan = 2;
		label.setLayoutData(data);
		label.setText(Messages.preferenceRuntimesDescription);
		
		label = new Label(composite, SWT.WRAP);
		data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
		data.horizontalSpan = 2;
		data.verticalIndent = 5;
		label.setLayoutData(data);
		label.setText(Messages.preferenceRuntimesTable);
		
		String[] moduleTypes = new String[] {RuntimeCore.JAXWS_MODULE_TYPE,
				RuntimeCore.SCA_MODULE_TYPE};
		final StpRuntimeCheckComposite runtimeComp = new StpRuntimeCheckComposite(
				composite, SWT.NONE, new StpRuntimeComposite.SelectionListener() {
			public void runtimeSelected(IRuntime runtime) {
				if (runtime == null) {
					edit.setEnabled(false);
					remove.setEnabled(false);
					pathLabel.setText("");
				} else if (runtime.isReadOnly()) {
					edit.setEnabled(false);
					remove.setEnabled(false);
					pathLabel.setText(runtime.getLocation() + "");
				} else {
					edit.setEnabled(true);
					remove.setEnabled(true);
					pathLabel.setText(runtime.getLocation() + "");
				}
			}
		},
		moduleTypes);
		runtimeComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL));
		
		Composite buttonComp = new Composite(composite, SWT.NONE);
		layout = new GridLayout();
		layout.horizontalSpacing = 0;
		layout.verticalSpacing = convertVerticalDLUsToPixels(3);
		layout.marginWidth = 0;
		layout.marginHeight = 0;
		layout.numColumns = 1;
		buttonComp.setLayout(layout);
		data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL);
		buttonComp.setLayoutData(data);
		
		Button add = SWTUtil.createButton(buttonComp, Messages.add);
		add.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				if (showWizard(null) == Window.CANCEL)
					return;
				runtimeComp.refresh();
				runtimeComp.updateDefault(null);
			}
		});
		
		edit = SWTUtil.createButton(buttonComp, Messages.edit);
		edit.setEnabled(false);
		edit.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				IRuntime runtime = runtimeComp.getSelectedRuntime();
				if (runtime != null) {
					IRuntimeWorkingCopy runtimeWorkingCopy = runtime.createWorkingCopy();
					if (showWizard(runtimeWorkingCopy) != Window.CANCEL) {
						try {
							runtimeComp.refresh(runtime);
						} catch (Exception ex) {
							// ignore
						}
					}
				}
			}
		});
		
		remove = SWTUtil.createButton(buttonComp, Messages.remove);
		remove.setEnabled(false);
		remove.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				IRuntime runtime = runtimeComp.getSelectedRuntime();
				if (shouldRemoveRuntime(runtime))
					try {
						runtime.delete();
						runtimeComp.remove(runtime);
						runtimeComp.updateDefault(runtime);
					} catch (Exception ex) {
						ex.printStackTrace();
						// ignore
					}
				
			}
		});
		
		Button search = SWTUtil.createButton(buttonComp, Messages.search);
		data = (GridData) search.getLayoutData();
		data.verticalIndent = 9;
		search.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				try {
					// select a target directory for the search
					DirectoryDialog directoryDialog = new DirectoryDialog(getShell());
					directoryDialog.setMessage(Messages.dialogRuntimeSearchMessage);
					directoryDialog.setText(Messages.dialogRuntimeSearchTitle);

					String pathStr = directoryDialog.open();
					if (pathStr == null)
						return;
					
					final IPath path = new Path(pathStr);
					
					final ProgressMonitorDialog dialog = new ProgressMonitorDialog(getShell());
					dialog.setBlockOnOpen(false);
					dialog.setCancelable(true);
					dialog.open();
					final IProgressMonitor monitor = dialog.getProgressMonitor();
					final IRuntimeLocator[] locators = ServerPlugin.getRuntimeLocators();
					monitor.beginTask(Messages.dialogRuntimeSearchProgress, 100 * locators.length + 10);
					final List list = new ArrayList();
					
					final IRuntimeLocator.IRuntimeSearchListener listener = new IRuntimeLocator.IRuntimeSearchListener() {
						public void runtimeFound(final IRuntimeWorkingCopy runtime) {
							dialog.getShell().getDisplay().syncExec(new Runnable() {
								public void run() {
									monitor.subTask(runtime.getName());
								}
							});
							list.add(runtime);
						}
					};
					
					IRunnableWithProgress runnable = new IRunnableWithProgress() {
						public void run(IProgressMonitor monitor2) {
							if (locators != null) {
								int size = locators.length;
								for (int i = 0; i < size; i++) {
									if (!monitor2.isCanceled())
										try {
											locators[i].searchForRuntimes(path, listener, monitor2);
										} catch (CoreException ce) {
											Trace.trace(Trace.WARNING, "Error locating runtimes: " + locators[i].getId(), ce);
										}
								}
							}
							Trace.trace(Trace.INFO, "Done search");
						}
					};
					dialog.run(true, true, runnable);
					
					Trace.trace(Trace.FINER, "Found runtimes: " + list.size());
					
					if (!monitor.isCanceled()) {
						if (list.isEmpty()) {
							EclipseUtil.openError(getShell(), Messages.infoNoRuntimesFound);
							return;
						}
						monitor.worked(5);
						// remove duplicates from list (based on location)
						Trace.trace(Trace.FINER, "Removing duplicates");
						List good = new ArrayList();
						Iterator iterator2 = list.iterator();
						while (iterator2.hasNext()) {
							boolean dup = false;
							IRuntime wc = (IRuntime) iterator2.next();
							
							IRuntime[] runtimes = ServerCore.getRuntimes();
							if (runtimes != null) {
								int size = runtimes.length;
								for (int i = 0; i < size; i++) {
									if (runtimes[i].getLocation() != null && runtimes[i].getLocation().equals(wc.getLocation()))
										dup = true;
								}
							}
							if (!dup)
								good.add(wc);
						}
						monitor.worked(5);
						
						// add to list
						Trace.trace(Trace.FINER, "Adding runtimes: " + good.size());
						Iterator iterator = good.iterator();
						while (iterator.hasNext()) {
							IRuntimeWorkingCopy wc = (IRuntimeWorkingCopy) iterator.next();
							wc.save(false, monitor);
						}
						monitor.done();
					}
					dialog.close();
				} catch (Exception ex) {
					Trace.trace(Trace.SEVERE, "Error finding runtimes", ex);
				}
				runtimeComp.refresh();
			}
		});
		
		pathLabel = new Label(parent, SWT.NONE);
		pathLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		
		Dialog.applyDialogFont(composite);
	
		return composite;
	}
	
	/**
	 * Johnson.Ma: we need to revisit this method later.
	 * This method is from wtp internal class. and is replaced 
	 * by removeRuntime() in wtp2.0 (Eclipes3.3).
	 * Since we want to keep the codebase compliance with eclipse3.2 for a while,
	 * we move the method here.
	 * This need to be removed once we drop the support for eclipse3.2
	 */
	protected boolean shouldRemoveRuntime(IRuntime runtime) {
		if (runtime == null)
			return false;

		// check for use
		boolean inUse = false;
	
		IServer[] servers = ServerCore.getServers();
		if (servers != null) {
			int size = servers.length;
			for (int i = 0; i < size; i++) {
				if (runtime.equals(servers[i].getRuntime()))
					inUse = true;
			}
		}
		
		
		if (inUse) {
			if (!MessageDialog.openConfirm(getShell(), Messages.defaultDialogTitle, Messages.dialogRuntimeInUse))
				return false;
		}
		
		return true;
	}
	
}
