/*******************************************************************************
 * Copyright (c) 2007 BEA Systems, Inc.
 * 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
 *******************************************************************************/
package org.eclipse.jst.j2ee.internal.classpathdep;

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

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jem.util.emf.workbench.ProjectUtilities;
import org.eclipse.jem.util.logger.proxy.Logger;
import org.eclipse.jst.j2ee.classpathdep.ClasspathDependencyUtil;
import org.eclipse.jst.j2ee.classpathdep.UpdateClasspathAttributeUtil;
import org.eclipse.jst.j2ee.internal.plugin.J2EEPlugin;
import org.eclipse.jst.j2ee.internal.project.J2EEProjectUtilities;
import org.eclipse.wst.common.frameworks.datamodel.AbstractDataModelOperation;
import org.eclipse.wst.common.frameworks.datamodel.IDataModel;

/**
 * DataModelOperation that updates the WTP component dependency attribute on the
 * the classpath entries for the target Java project.
 */
public class UpdateClasspathAttributesOperation extends AbstractDataModelOperation implements UpdateClasspathAttributesDataModelProperties {

	public UpdateClasspathAttributesOperation(final IDataModel dataModel) {
		super(dataModel);
	}
	
	public IStatus execute(final IProgressMonitor monitor, final IAdaptable info)
			throws ExecutionException {
		final IProject project = ProjectUtilities.getProject(model.getStringProperty(PROJECT_NAME));

		try {
			if (project.hasNature(JavaCore.NATURE_ID)) {
				final IJavaProject javaProject = JavaCore.create(project);
				validateEdit(project);
				final Map entriesToAdd = (Map) model.getProperty(ENTRIES_TO_ADD_ATTRIBUTE);
				final boolean modifyComponentDep = model.getBooleanProperty(MODIFY_CLASSPATH_COMPONENT_DEPENDENCY);
				if (entriesToAdd == null) {
					final Map entriesToRemove = (Map ) model.getProperty(ENTRIES_TO_REMOVE_ATTRIBUTE);
					if (entriesToRemove == null) {
						final Map entriesToRuntimePath = (Map) model.getProperty(ENTRIES_WITH_ATTRIBUTE);
						final Map entriesToAttrib = new HashMap();
						final Iterator i = entriesToRuntimePath.keySet().iterator();
						while (i.hasNext()) {
							IClasspathEntry entry = (IClasspathEntry) i.next();
							IPath runtimePath = (IPath) entriesToRuntimePath.get(entry);
							IClasspathAttribute attrib = ClasspathDependencyUtil.checkForComponentDependencyAttribute(entry, 
									modifyComponentDep ? DependencyAttributeType.CLASSPATH_COMPONENT_DEPENDENCY : DependencyAttributeType.CLASSPATH_COMPONENT_NONDEPENDENCY);
							if (attrib == null) {
								if (modifyComponentDep) {
									attrib = UpdateClasspathAttributeUtil.createDependencyAttribute(runtimePath);
								} else {
									attrib = UpdateClasspathAttributeUtil.createNonDependencyAttribute();
								}
							}
							entriesToAttrib.put(entry, attrib);
						}
						updateDependencyAttributes(javaProject, entriesToAttrib, modifyComponentDep); 
					} else {
						removeDependencyAttributes(javaProject, entriesToRemove, modifyComponentDep); 
					}
				} else {
					
					addDependencyAttributes(javaProject, entriesToAdd, modifyComponentDep); 
				}
			}
		} catch (CoreException ce) {
			Logger.getLogger(J2EEPlugin.PLUGIN_ID).logError(ce);
			return new Status(IStatus.ERROR, J2EEPlugin.PLUGIN_ID, 0, ce.getLocalizedMessage(), ce);
		}
		return Status.OK_STATUS;
	}

	/**
	 * Performs a validateEdit call on the files impacted by the operation.
	 */
	protected void validateEdit(final IProject project) throws CoreException {
		final List affectedFiles = ProjectUtilities.getFilesAffectedByClasspathChange(project);
		final IFile[] files = (IFile[]) affectedFiles.toArray(new IFile[affectedFiles.size()]);
		final IStatus result = J2EEPlugin.getWorkspace().validateEdit(files, null);
		if (!result.isOK()) {
			throw new CoreException(result);
		}
	}
	
	/**
	 * Adds the WTP component dependency attribute to the specified classpath entries.
	 * @param javaProject Target Java project.
	 * @param entries Classpath entries to which the component dependency attribute should be added.
 	 * @param modifyComponentDep True if adding the dependency attribute, false if adding the non-dependency attribute.
	 * @throws CoreException Thrown if an error is encountered.
	 */	
	private void addDependencyAttributes(final IJavaProject javaProject, final Map entries, final boolean modifyComponentDep) throws CoreException {
		alterDependencyAttributes(javaProject, entries, true, modifyComponentDep);
	}
	
	/**
	 * Removes the WTP component dependency attribute from the specified classpath entries.
	 * @param javaProject Target Java project.
	 * @param entries Classpath entries from which the component dependency attribute should be removed.
	 * @param modifyComponentDep True if removing the dependency attribute, false if removing the non-dependency attribute.
	 * @throws CoreException Thrown if an error is encountered.
	 */	
	private void removeDependencyAttributes(final IJavaProject javaProject, final Map entries, final boolean modifyComponentDep) throws CoreException {
		alterDependencyAttributes(javaProject, entries, false, modifyComponentDep);
	}

	private void alterDependencyAttributes(final IJavaProject javaProject, final Map entries, final boolean add, final boolean modifyComponentDep) throws CoreException {
		// initialize to the set of raw entries with the attrib
		final Map entriesWithAttrib = ClasspathDependencyUtil.getRawComponentClasspathDependencies(javaProject);
		
		Iterator i = entries.keySet().iterator();
		while (i.hasNext()) {
			final IClasspathEntry entry = (IClasspathEntry) i.next();
			if (add) {
				if (getMatchingEntryIgnoreAttributes(entriesWithAttrib, entry) == null) {
					IPath runtimePath = (IPath) entries.get(entry);
					if (runtimePath == null) {
						// compute the default runtime path
						final boolean isWebApp = J2EEProjectUtilities.isDynamicWebProject(javaProject.getProject());
						runtimePath = ClasspathDependencyUtil.getDefaultRuntimePath(isWebApp, ClasspathDependencyUtil.isClassFolderEntry(entry));
					}
					IClasspathAttribute attrib = null;
					if (modifyComponentDep) {
						attrib = UpdateClasspathAttributeUtil.createDependencyAttribute(runtimePath);
					} else {
						attrib = UpdateClasspathAttributeUtil.createNonDependencyAttribute();
					}
 					entriesWithAttrib.put(entry, attrib);
				}
			} else {
				IClasspathEntry matching = getMatchingEntryIgnoreAttributes(entriesWithAttrib, entry);
				if (matching != null) {
					entriesWithAttrib.remove(matching);
				}
			}
		}
		updateDependencyAttributes(javaProject, entriesWithAttrib, modifyComponentDep);
	}
	
	private IClasspathEntry getMatchingEntryIgnoreAttributes(final Map entries, final IClasspathEntry entry) {
		final Iterator i = entries.keySet().iterator();
		while (i.hasNext()) {
			final IClasspathEntry e = (IClasspathEntry) i.next();
			if (e.getEntryKind() == entry.getEntryKind()
					&& e.getPath().equals(entry.getPath())
					&& e.isExported() == entry.isExported()) {
				return e;
			}
		}
		return null;

	}

	/**
	 * Updates the specified Java project so that only the specified classpath entries have
	 * the WTP component dependency attribute.
	 * @param javaProject Target Java project.
	 * @param entries Classpath entries that should have the component dependency attribute. Map from IClasspathEntry
	 * to the IClasspathAttribute for the WTP classpath component dependency.
	 * @param modifyComponentDep True if modifying the dependency attribute, false if modifying the non-dependency attribute.
	 * @throws CoreException Thrown if an error is encountered.
	 */	
	private void updateDependencyAttributes(final IJavaProject javaProject, final Map entriesWithAttrib, final boolean modifyComponentDep) throws CoreException {
		if (javaProject == null || !javaProject.getProject().isAccessible()) {
			return;
		}
		
		final List updatedClasspath = new ArrayList();
		final IClasspathEntry[] rawClasspath = javaProject.getRawClasspath();
		boolean needToUpdateClasspath = false;
		IClasspathAttribute attrib = UpdateClasspathAttributeUtil.createDependencyAttribute();
		if (!modifyComponentDep) {
			attrib = UpdateClasspathAttributeUtil.createNonDependencyAttribute();
		}
		for (int i = 0; i < rawClasspath.length; i++) {
			IClasspathEntry entry = rawClasspath[i];
			final int kind = entry.getEntryKind();
			boolean hasAttribute = ClasspathDependencyUtil.checkForComponentDependencyAttribute(entry, 
					modifyComponentDep ? DependencyAttributeType.CLASSPATH_COMPONENT_DEPENDENCY : DependencyAttributeType.CLASSPATH_COMPONENT_NONDEPENDENCY) != null;
			boolean shouldHaveAttribute = entriesWithAttrib.containsKey(entry);
			boolean updateAttributes = false;
			IClasspathAttribute[] updatedAttributes = null;
			if (shouldHaveAttribute) {
				if (!hasAttribute) {
					// should have the attribute and currently missing it
					attrib = (IClasspathAttribute) entriesWithAttrib.get(entry);
					updatedAttributes = updateAttributes(entry.getExtraAttributes(), attrib, true);
					needToUpdateClasspath = true;
					updateAttributes = true;
				}
			} else if (hasAttribute) {
				// should not have the attribute and currently has it
				updatedAttributes = updateAttributes(entry.getExtraAttributes(), attrib, false);
				needToUpdateClasspath = true;
				updateAttributes = true;				
			}
			
			if (updateAttributes) {
				switch(kind) {
				case IClasspathEntry.CPE_CONTAINER:
					entry = JavaCore.newContainerEntry(entry.getPath(), entry.getAccessRules(), updatedAttributes, entry.isExported());
					break;
				case IClasspathEntry.CPE_LIBRARY:
					entry = JavaCore.newLibraryEntry(entry.getPath(), entry.getSourceAttachmentPath(), entry.getSourceAttachmentRootPath(), entry.getAccessRules(), updatedAttributes, entry.isExported());
					break;
				case IClasspathEntry.CPE_VARIABLE:
					entry = JavaCore.newVariableEntry(entry.getPath(), entry.getSourceAttachmentPath(), entry.getSourceAttachmentRootPath(), entry.getAccessRules(), updatedAttributes, entry.isExported());
					break;					
				case IClasspathEntry.CPE_PROJECT: // although project entries are not yet supported, allow the attribute here and let the validator flag as an error
					entry = JavaCore.newProjectEntry(entry.getPath(), entry.getAccessRules(), entry.combineAccessRules(), updatedAttributes, entry.isExported());
					break;										
				case IClasspathEntry.CPE_SOURCE: // although source entries are not supported, allow the attribute here and let the validator flag as an error
					entry = JavaCore.newSourceEntry(entry.getPath(), entry.getInclusionPatterns(), entry.getExclusionPatterns(), entry.getOutputLocation(), updatedAttributes);
					break;															
				}
			}
			
			updatedClasspath.add(entry);
		}
		if (needToUpdateClasspath) {
			final IClasspathEntry[] updatedCPArray = (IClasspathEntry[]) updatedClasspath.toArray(new IClasspathEntry[updatedClasspath.size()]);
			javaProject.setRawClasspath(updatedCPArray, null);
		}
	}

	private IClasspathAttribute[] updateAttributes(final IClasspathAttribute[] currentAttribs, final IClasspathAttribute targetAttrib, final boolean add) {
		final List updatedAttribs = new ArrayList();
		boolean hasAttrib = false;
		for (int i = 0; i < currentAttribs.length; i++) {
			if (currentAttribs[i].getName().equals(targetAttrib.getName())) {
				hasAttrib = true;
				if (!add) {
					continue;
				}
			}
			updatedAttribs.add(currentAttribs[i]);
		}
		if (add && !hasAttrib) {
			updatedAttribs.add(targetAttrib);
		}
		return (IClasspathAttribute[]) updatedAttribs.toArray(new IClasspathAttribute[updatedAttribs.size()]);
	}
}
