/*******************************************************************************
 * Copyright (c) 2003, 2005 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.j2ee.internal.common.operations;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jst.j2ee.application.internal.operations.ClassPathSelection;
import org.eclipse.jst.j2ee.application.internal.operations.ClasspathElement;
import org.eclipse.wst.common.frameworks.internal.DoNotUseMeThisWillBeDeletedPost15;
import org.eclipse.wst.common.frameworks.internal.enablement.nonui.WFTWrappedException;
import org.eclipse.wst.common.frameworks.internal.operations.IHeadlessRunnableWithProgress;

/**
 * {@link DoNotUseMeThisWillBeDeletedPost15}
 * 
 * @deprecated This should no longer be necessary because of the new EAR & Web Lib classpath
 *             containers
 */
public class UpdateJavaBuildPathOperation implements IHeadlessRunnableWithProgress {
	protected IJavaProject javaProject;
	protected ClassPathSelection classPathSelection;
	// All the Java build path entries created by the classpath selection
	protected Set allClasspathEntries;
	protected List allUnselectedClasspathEntries;

	/**
	 * UpdateJavaBuildPathOperation constructor comment.
	 */
	public UpdateJavaBuildPathOperation(IJavaProject aJavaProject, ClassPathSelection aClassPathSelection) {
		super();
		javaProject = aJavaProject;
		classPathSelection = aClassPathSelection;
		allClasspathEntries = new HashSet();
		IClasspathEntry[] classpathEntry = aClassPathSelection.getClasspathEntriesForSelected();
		if (classpathEntry != null)
			allClasspathEntries.addAll(Arrays.asList(classpathEntry));
	}

	/**
	 * UpdateJavaBuildPathOperation constructor comment.
	 */
	public UpdateJavaBuildPathOperation(IJavaProject aJavaProject, ClassPathSelection selected, ClassPathSelection unselected) {
		super();
		javaProject = aJavaProject;
		classPathSelection = selected;
		allClasspathEntries = new HashSet();
		if (selected != null && !selected.getClasspathElements().isEmpty())
			allClasspathEntries.addAll(Arrays.asList(selected.getClasspathEntriesForSelected()));

		allUnselectedClasspathEntries = new ArrayList();
		if (unselected != null && !unselected.getClasspathElements().isEmpty())
			allUnselectedClasspathEntries.addAll(unselected.getClasspathElements());
	}

	public UpdateJavaBuildPathOperation(IJavaProject aJavaProject, ClassPathSelection selected, List unselected) {
		super();
		javaProject = aJavaProject;
		classPathSelection = selected;
		allClasspathEntries = new HashSet();
		if (selected != null && !selected.getClasspathElements().isEmpty())
			allClasspathEntries.addAll(Arrays.asList(selected.getClasspathEntriesForSelected()));

		allUnselectedClasspathEntries = new ArrayList();
		if (unselected != null && !unselected.isEmpty())
			allUnselectedClasspathEntries.addAll(unselected);
	}

	protected void ensureClasspathEntryIsExported(List cp, IClasspathEntry entry) {
		if (entry.isExported())
			return;
		int index = getIndex(cp, entry);
		IClasspathEntry newEntry = null;
		switch (entry.getEntryKind()) {
			case IClasspathEntry.CPE_PROJECT :
				newEntry = JavaCore.newProjectEntry(entry.getPath(), true);
				break;
			case IClasspathEntry.CPE_LIBRARY :
				newEntry = JavaCore.newLibraryEntry(entry.getPath(), entry.getSourceAttachmentPath(), entry.getSourceAttachmentRootPath(), true);
				break;
			case IClasspathEntry.CPE_VARIABLE :
				newEntry = JavaCore.newVariableEntry(entry.getPath(), entry.getSourceAttachmentPath(), entry.getSourceAttachmentRootPath());
			default :
				break;
		}
		if (entry != null)
			cp.set(index, newEntry);
	}

	protected IClasspathEntry ensureElementInList(List cp, ClasspathElement element, IClasspathEntry predecessor) {
		IClasspathEntry addedEntry = null;
		// The element might have multiple entries in the case of
		// the imported_classes.jar file
		IClasspathEntry[] cpEntries = element.newClasspathEntries();
		if (cpEntries == null || cpEntries.length == 0)
			// indicates an invalid entry
			return null;

		int predecessorPos = predecessor == null ? -1 : getIndex(cp, predecessor);
		addedEntry = cpEntries[0];
		// Ensure that the first item is in the list, and follows
		// the predecessor if specified; preserve existing items in
		// the case of source attachments
		int pos = getIndex(cp, addedEntry);
		if (pos == -1) {
			if (predecessorPos == -1)
				cp.add(addedEntry);
			else
				cp.add(predecessorPos + 1, addedEntry);
		} else {
			addedEntry = (IClasspathEntry) cp.get(pos);
			if (pos < predecessorPos) {
				cp.remove(addedEntry);
				cp.add(predecessorPos, addedEntry);
			}
		}
		ensureClasspathEntryIsExported(cp, addedEntry);

		// Remove and add so we can ensure the proper order; this
		// is the case of the imported_classes.jar; we always want it
		// directly after the project
		for (int i = 1; i < cpEntries.length; i++) {
			int index = getIndex(cp, cpEntries[i]);
			if (index != -1) {
				addedEntry = (IClasspathEntry) cp.get(index);
				cp.remove(index);
			} else
				addedEntry = cpEntries[i];
			pos = getIndex(cp, cpEntries[0]);
			cp.add(pos + 1, addedEntry);
		}
		return addedEntry;
	}

	protected int getIndex(List cp, IClasspathEntry entry) {
		for (int i = 0; i < cp.size(); i++) {
			IClasspathEntry elmt = (IClasspathEntry) cp.get(i);
			if (elmt.getPath().equals(entry.getPath()))
				return i;
		}
		return -1;
	}

	protected void ensureElementNotInList(List cp, ClasspathElement element) {
		IClasspathEntry[] cpEntries = element.newClasspathEntries();
		if (cpEntries == null || cpEntries.length == 0)
			return;
		for (int i = 0; i < cpEntries.length; i++) {
			if (allClasspathEntries.contains(cpEntries[i]))
				// This may be included indirectly by a transitive dependency
				continue;
			int index = getIndex(cp, cpEntries[i]);
			if (index != -1)
				cp.remove(index);
		}
	}

	protected void ensureRemoveElementInList(List cp, ClasspathElement element) {
		IClasspathEntry[] cpEntries = element.newClasspathEntries();
		if (cpEntries == null || cpEntries.length == 0)
			return;
		for (int i = 0; i < cpEntries.length; i++) {
			if (cp.contains(cpEntries[i])) {
				int index = getIndex(cp, cpEntries[i]);
				if (index != -1)
					cp.remove(index);
			}
		}
	}

	/**
	 * Runs this operation. Progress should be reported to the given progress monitor. This method
	 * is usually invoked by an <code>IRunnableContext</code>'s<code>run</code> method, which
	 * supplies the progress monitor. A request to cancel the operation should be honored and
	 * acknowledged by throwing <code>InterruptedException</code>.
	 * 
	 * @param monitor
	 *            the progress monitor to use to display progress and receive requests for
	 *            cancelation
	 * @exception InvocationTargetException
	 *                if the run method must propagate a checked exception, it should wrap it inside
	 *                an <code>InvocationTargetException</code>; runtime exceptions are
	 *                automatically wrapped in an <code>InvocationTargetException</code> by the
	 *                calling context
	 * @exception InterruptedException
	 *                if the operation detects a request to cancel, using
	 *                <code>IProgressMonitor.isCanceled()</code>, it should exit by throwing
	 *                <code>InterruptedException</code>
	 * 
	 * @see IRunnableContext#run
	 */
	public void run(org.eclipse.core.runtime.IProgressMonitor monitor) throws java.lang.reflect.InvocationTargetException, InterruptedException {
		try {
			String[] prevRequiredProjects = javaProject.getRequiredProjectNames();
			List cp = new ArrayList(Arrays.asList(javaProject.getRawClasspath()));
			List classpathElements = classPathSelection.getClasspathElements();
			IClasspathEntry predecessor = null;
			IClasspathEntry result = null;
			for (int i = 0; i < classpathElements.size(); i++) {
				ClasspathElement element = (ClasspathElement) classpathElements.get(i);
				if (element.isSelected()) {
					result = ensureElementInList(cp, element, predecessor);
					if (result != null)
						predecessor = result;
				} else
					ensureElementNotInList(cp, element);
			}
			filterUnselectedEntries(cp);
			IClasspathEntry[] newCp = ((IClasspathEntry[]) cp.toArray(new IClasspathEntry[cp.size()]));
			javaProject.setRawClasspath(newCp, monitor);
			updateRequiredProjects(javaProject, prevRequiredProjects, new SubProgressMonitor(monitor, 1));
		} catch (Exception ex) {
			throw new WFTWrappedException(ex);
		}
	}

	private void filterUnselectedEntries(List cp) {
		if (allUnselectedClasspathEntries != null) {
			for (int i = 0; i < allUnselectedClasspathEntries.size(); i++) {
				ClasspathElement element = (ClasspathElement) allUnselectedClasspathEntries.get(i);
				ensureRemoveElementInList(cp, element);
			}
		}
	}

	protected void updateRequiredProjects(IJavaProject jproject, String[] prevRequiredProjects, IProgressMonitor monitor) throws CoreException {
		String[] newRequiredProjects = jproject.getRequiredProjectNames();

		ArrayList prevEntries = new ArrayList(Arrays.asList(prevRequiredProjects));
		ArrayList newEntries = new ArrayList(Arrays.asList(newRequiredProjects));

		IProject proj = jproject.getProject();
		IProjectDescription projDesc = proj.getDescription();

		ArrayList newRefs = new ArrayList();
		IProject[] referencedProjects = projDesc.getReferencedProjects();
		for (int i = 0; i < referencedProjects.length; i++) {
			String curr = referencedProjects[i].getName();
			if (newEntries.remove(curr) || !prevEntries.contains(curr)) {
				newRefs.add(referencedProjects[i]);
			}
		}
		IWorkspaceRoot root = proj.getWorkspace().getRoot();
		for (int i = 0; i < newEntries.size(); i++) {
			String curr = (String) newEntries.get(i);
			newRefs.add(root.getProject(curr));
		}
		projDesc.setReferencedProjects((IProject[]) newRefs.toArray(new IProject[newRefs.size()]));
		proj.setDescription(projDesc, monitor);
	}
}
