/*
 * Copyright (c) 2009 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 - Base Code
 *     Red Hat - Refactor for CNF
 */

package org.eclipse.wst.server.ui.internal.cnf;

import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.*;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.util.LocalSelectionTransfer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.navigator.CommonDropAdapter;
import org.eclipse.ui.navigator.CommonDropAdapterAssistant;
import org.eclipse.wst.server.core.*;
import org.eclipse.wst.server.core.internal.ServerPlugin;
import org.eclipse.wst.server.ui.internal.EclipseUtil;
import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
import org.eclipse.wst.server.ui.internal.actions.RunOnServerActionDelegate;

public class ServersViewDropAdapterAssistant extends CommonDropAdapterAssistant {

	private List dndElementList;

	public IStatus validatePluginTransferDrop(
			IStructuredSelection aDragSelection, Object aDropTarget) {
		initializeSelection(aDragSelection);
		return internalValidate(aDropTarget, dndElementList);
	}

	public IStatus validateDrop(Object target, int operation,
			TransferData transferType) {
		if (LocalSelectionTransfer.getTransfer().isSupportedType(transferType)) {
			ISelection s = LocalSelectionTransfer.getTransfer().getSelection();
			initializeSelection(s);
			return internalValidate(target, dndElementList);
		}
		return Status.CANCEL_STATUS;
	}

	protected void initializeSelection(ISelection s) {
		if (dndElementList != null)
			return;
		if (!(s instanceof IStructuredSelection)) {
			dndElementList = Collections.EMPTY_LIST;
			return;
		}
		dndElementList = ((IStructuredSelection) s).toList();
	}

	protected IStatus internalValidate(Object target, List elements) {
		if (target instanceof IServer) {
			IServer server = (IServer) target;
			Object next;
			if (elements != null) {
				Iterator i = elements.iterator();
				while (i.hasNext()) {
					next = i.next();
					IModuleArtifact[] moduleArtifacts = ServerPlugin
							.getModuleArtifacts(next);
					if (moduleArtifacts != null && moduleArtifacts.length > 0) {
						for (int j = 0; j < moduleArtifacts.length; j++) {
							if (moduleArtifacts[j] != null
									&& moduleArtifacts[j].getModule() != null) {
								IModuleType[] moduleTypes = server
										.getServerType().getRuntimeType()
										.getModuleTypes();
								if (ServerUtil.isSupportedModule(moduleTypes,
										moduleArtifacts[j].getModule()
												.getModuleType())) {
									return Status.OK_STATUS;
								}
							}
						}
					}
				}
			}
		}
		clear();
		return Status.CANCEL_STATUS;
	}

	public IStatus handleDrop(CommonDropAdapter dropAdapter, DropTargetEvent dropTargetEvent, Object target) {
		IStatus status = internalHandleDrop(target, dndElementList);
		if (status.isOK())
			dropTargetEvent.detail = DND.DROP_NONE;
		return status;
	}

	public IStatus handlePluginTransferDrop(IStructuredSelection aDragSelection, Object aDropTarget) {
		return internalHandleDrop(aDropTarget, dndElementList);
	}

	protected IStatus internalHandleDrop(Object target, List elements) {
		boolean b = false;
		if (target instanceof IServer) {
			b = true;
			if (dndElementList != null) {
				Iterator iterator = elements.iterator();
				while (iterator.hasNext()) {
					Object data2 = iterator.next();
					if (!doRunOnServerAction((IServer) target, data2))
						b = false;
				}
			}
		}
		clear();
		return b ? Status.OK_STATUS : Status.CANCEL_STATUS;
	}

	private void clear() {
		dndElementList = null;
	}

	protected boolean doRunOnServerAction(IServer server, Object data) {
		// check if the selection is a project (module) that we can add to the server
		IProject project = (IProject) Platform.getAdapterManager().getAdapter(
				data, IProject.class);
		if (project != null) {
			IModule[] modules = ServerUtil.getModules(project);
			if (modules != null && modules.length == 1) {
				try {
					IServerWorkingCopy wc = server.createWorkingCopy();
					IModule[] parents = wc.getRootModules(modules[0], null);
					if (parents == null || parents.length == 0)
						return false;

					if (ServerUtil.containsModule(server, parents[0], null))
						return false;

					IModule[] add = new IModule[] { parents[0] };
					if (wc.canModifyModules(add, null, null).getSeverity() != IStatus.ERROR) {
						wc.modifyModules(modules, null, null);
						wc.save(false, null);
						return true;
					}
				} catch (final CoreException ce) {
					final Shell shell = getShell();
					shell.getDisplay().asyncExec(new Runnable() {
						public void run() {
							EclipseUtil.openError(shell, ce
									.getLocalizedMessage());
						}
					});
					return true;
				}
			}
		}

		// otherwise, try Run on Server
		final IServer finalServer = server;
		RunOnServerActionDelegate ros = new RunOnServerActionDelegate() {
			public IServer getServer(IModule module,
					IModuleArtifact moduleArtifact, IProgressMonitor monitor)
					throws CoreException {
				if (!ServerUIPlugin.isCompatibleWithLaunchMode(finalServer,
						launchMode))
					return null;

				if (!ServerUtil.containsModule(finalServer, module, monitor)) {
					IServerWorkingCopy wc = finalServer.createWorkingCopy();
					try {
						ServerUtil.modifyModules(wc, new IModule[] { module },
								new IModule[0], monitor);
						wc.save(false, monitor);
					} catch (CoreException ce) {
						throw ce;
					}
				}

				return finalServer;
			}
		};
		Action action = new Action() {
			// dummy action
		};
		ros.selectionChanged(action, new StructuredSelection(data));

		ros.run(action);
		return true;
	}
}
