/*******************************************************************************
 * 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.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.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());
		}
		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);
	}
}
