/*******************************************************************************
 * Copyright (c) 2005, 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
 * 
 * Contributors:
 * rfrost@bea.com - initial API and implementation
 *******************************************************************************/
package org.eclipse.jst.j2ee.refactor.listeners;

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

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.WorkspaceJob;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.ElementChangedEvent;
import org.eclipse.jdt.core.IElementChangedListener;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaElementDelta;
import org.eclipse.jdt.core.IJavaModel;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jem.util.logger.proxy.Logger;
import org.eclipse.jst.j2ee.internal.J2EEConstants;
import org.eclipse.jst.j2ee.internal.plugin.J2EEPlugin;
import org.eclipse.jst.j2ee.internal.project.J2EEProjectUtilities;
import org.eclipse.wst.common.componentcore.ComponentCore;
import org.eclipse.wst.common.componentcore.ModuleCoreNature;
import org.eclipse.wst.common.componentcore.internal.ComponentResource;
import org.eclipse.wst.common.componentcore.internal.StructureEdit;
import org.eclipse.wst.common.componentcore.internal.WorkbenchComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualFolder;

/**
 * Implementation of <code>IElementChangedListener that updates mappings for src folders
 * in the .component file in response to changes in a project's Java classpath. 
 */
public class J2EEElementChangedListener implements IElementChangedListener {

	/**
	 * Name of the Job family in which all component update jobs belong.
	 */
	public static final String PROJECT_COMPONENT_UPDATE_JOB_FAMILY =  "org.eclipse.jst.j2ee.refactor.component"; //$NON-NLS-1$
	
	
	/* (non-Javadoc)
	 * @see org.eclipse.jdt.core.IElementChangedListener#elementChanged(org.eclipse.jdt.core.ElementChangedEvent)
	 */
	public void elementChanged(final ElementChangedEvent event) {
		processJavaElementDelta(event.getDelta());
	}
	
	private void processJavaElementDelta(final IJavaElementDelta delta) {
		final int kind = delta.getKind();
		if (kind == IJavaElementDelta.CHANGED) {
			final int flags = delta.getFlags();
			final IJavaElement element = delta.getElement();
			if (element instanceof IJavaModel) {
				if ((flags & IJavaElementDelta.F_CHILDREN) == IJavaElementDelta.F_CHILDREN) {
					final IJavaElementDelta[] children = delta.getChangedChildren();
					for (int i = 0; i < children.length; i++) {
						// handle all of the IJavaProject children
						processJavaElementDelta(children[i]);
					}
				} else {
					// not a Java project (i.e. could be an EAR project)
					processResourceDeltas(flags, kind, delta);
				}
			} else if (element instanceof IJavaProject) {
				processJavaProject((IJavaProject) element, flags, kind, delta);
			}
		}
	}
	
	private void processJavaProject(final IJavaProject jproject, final int flags, final int kind, final IJavaElementDelta delta) {

		final IProject project = jproject.getProject();
		final List pathsToAdd = new ArrayList();
		final List pathsToRemove = new ArrayList();
		final List changedJavaPaths = new ArrayList();
		
		// make certain this is a J2EE project
		if (ModuleCoreNature.getModuleCoreNature(project) != null) {
			IVirtualComponent c = ComponentCore.createComponent(project);
			try {
				// Did the classpath change?
				if ((flags & IJavaElementDelta.F_CHILDREN) == IJavaElementDelta.F_CHILDREN) {
					final boolean cpChanged = (flags & IJavaElementDelta.F_CLASSPATH_CHANGED) != 0; 
					getJavaSrcMappings(c, delta.getAffectedChildren(), cpChanged, jproject, pathsToAdd, pathsToRemove, changedJavaPaths);
				}

				// Did a non-Java folder change name?
				final IResourceDelta[] deltas = delta.getResourceDeltas();
				if (deltas != null && deltas.length > 0) {
					getNonJavaFolderMappings(deltas, c, pathsToAdd, pathsToRemove, changedJavaPaths);
				}
		
			} catch (CoreException ce) {
				Logger.getLogger(J2EEPlugin.PLUGIN_ID).logError(ce);
				return;
			}
			updateMappingsInJob(pathsToAdd, pathsToRemove);
		}		
	}
	
	private void processResourceDeltas(final int flags, final int kind, final IJavaElementDelta delta) {
		final List pathsToAdd = new ArrayList();
		final List pathsToRemove = new ArrayList();

		final IResourceDelta[] deltas = delta.getResourceDeltas();
		if (deltas != null && deltas.length > 0) {
			try {
				getNonJavaFolderMappings(deltas, null, pathsToAdd, pathsToRemove, Collections.EMPTY_LIST);
			} catch (CoreException ce) {
				Logger.getLogger(J2EEPlugin.PLUGIN_ID).logError(ce);
				return;
			}
		}
		
		updateMappingsInJob(pathsToAdd, pathsToRemove);
	}
	
	/*
	 * Adds and removes the specified component resource mappings in a WorkspaceJob
	 */
	private void updateMappingsInJob(final List pathsToAdd, final List pathsToRemove) {
		// If there are corrections to the virtual path mappings, execute them in a Job
		if (!pathsToAdd.isEmpty() || !pathsToRemove.isEmpty()) {
			WorkspaceJob job = new WorkspaceJob("J2EEComponentMappingUpdateJob") {							
				public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
					for(int i=0;i<pathsToAdd.size(); i++){
						Object[] toAdd = (Object[]) pathsToAdd.get(i);
						final IVirtualFolder destFolder = (IVirtualFolder) toAdd[1];
						final IPath pathToAdd = (IPath) toAdd[0];
						destFolder.createLink(pathToAdd, 0, monitor);
					}
					for(int i=0;i<pathsToRemove.size(); i++){
						Object[] toRemove = (Object[]) pathsToRemove.get(i);
						final IVirtualFolder destFolder = (IVirtualFolder) toRemove[1];
						final IPath pathToRemove = (IPath) toRemove[0];
						destFolder.removeLink(pathToRemove, 0, monitor);
					}
					return Status.OK_STATUS;
				}
				public boolean belongsTo(final Object family) {
					return PROJECT_COMPONENT_UPDATE_JOB_FAMILY.equals(family);
				}
			};
			job.setRule(ResourcesPlugin.getWorkspace().getRoot());
			job.schedule();
		}						
	}
	
	/*
	 * Computes the virtual component path mapping changes the need to be made due to 
	 * Java src path changes.
	 */ 
	private void getJavaSrcMappings(final IVirtualComponent virtualComp, final IJavaElementDelta[] children, final boolean cpChanged, final IJavaProject jproject, final List pathsToAdd, final List pathsToRemove, final List changedPaths) 
		throws CoreException {
		
		// get the default destination folder
		final IVirtualFolder defaultDestFolder = getDestinationFolder(virtualComp);
		
		for (int i = 0; i < children.length; i++) {
			final IJavaElementDelta delta = children[i];
			final IJavaElement element = delta.getElement();
			if(element.getElementType() == IJavaElement.PACKAGE_FRAGMENT_ROOT){
				final IPackageFragmentRoot root = (IPackageFragmentRoot) element;
				int cpeKind = IPackageFragmentRoot.K_SOURCE;
				boolean abortAdd = false;
				try {
					cpeKind = root.getKind();
				} catch (JavaModelException jme) {
					// this is thrown if the folder corresponding to the CPE has been deleted
					// since it could represent another error, we need to abort adding. 
					abortAdd = true;
				}
				// only update if we know it is a src folder
				if (cpeKind == IPackageFragmentRoot.K_SOURCE) {
					final int kind = delta.getKind();					
					if (!cpChanged) {
						// if the classpath is not changed, save modifications to the Java src path
						if (kind == IJavaElementDelta.CHANGED || kind == IJavaElementDelta.REMOVED) {
							changedPaths.add(root.getPath().removeFirstSegments(1));		
						}
					} else {
					
						// kind and flags for CP additions are somewhat sporadic; either:
						// -kind is ADDED and flags are 0
						//   or
						// -kind is CHANGED and flags are F_ADDED_TO_CLASSPATH
						final int flags = delta.getFlags();

						if (kind == IJavaElementDelta.ADDED || 
								(flags & IJavaElementDelta.F_ADDED_TO_CLASSPATH) == IJavaElementDelta.F_ADDED_TO_CLASSPATH) {
							if (!abortAdd) {
								final IPath pathToAdd = root.getPath().removeFirstSegments(1);
								pathsToAdd.add(new Object[]{pathToAdd, defaultDestFolder});
								// if the added src path was moved from another location, remove any mapping for that
								// location
								if ((flags & IJavaElementDelta.F_MOVED_FROM) == IJavaElementDelta.F_MOVED_FROM) {
									final IJavaElement movedFromElement = delta.getMovedFromElement();
									final IPath pathToRemove = movedFromElement.getPath().removeFirstSegments(1);
									pathsToRemove.add(new Object[]{pathToRemove, defaultDestFolder});
								}
							}
							// getting a kind = REMOVED and flags = 0 for removal of the folder (w/o removing the CPE), probably
							// should not be generated
						} else if ((flags & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) == IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) {
							IPath path = root.getPath().removeFirstSegments(1);
							pathsToRemove.add(new Object[]{path, defaultDestFolder});
						} 
					}			
				}
			}
		}
	}
	
	/*
	 * Computes the virtual component path mapping changes the need to be made due to changes to
	 * non-Java folders. 
	 */ 
	private void getNonJavaFolderMappings(final IResourceDelta[] deltas, final IVirtualComponent virtualComp, final List pathsToAdd, final List pathsToRemove, final List changedJavaPaths) throws CoreException {
		IVirtualFolder rootFolder = null;
		if (virtualComp != null) {
			rootFolder = virtualComp.getRootFolder();
		}
		Map sourceToRuntime = null;
		if (virtualComp != null) {
			sourceToRuntime = getResourceMappings(virtualComp.getProject());
		}
		for (int i = 0; i < deltas.length; i++) {
			final IResourceDelta delta = deltas[i];
			processResourceDelta(delta, rootFolder, sourceToRuntime, pathsToAdd, pathsToRemove, changedJavaPaths);
		}
	}
	
	/*
	 * Processes a single IResourceDelta.
	 */
	private void processResourceDelta(final IResourceDelta delta, IVirtualFolder rootFolder, Map sourceToRuntime, final List pathsToAdd, final List pathsToRemove, final List changedJavaPaths) throws CoreException {
		final int kind = delta.getKind();
		if (kind == IResourceDelta.CHANGED) {
			IResourceDelta[] childDeltas = delta.getAffectedChildren();
			for (int i = 0; i < childDeltas.length; i++) {
				processResourceDelta(childDeltas[i], rootFolder, sourceToRuntime, pathsToAdd, pathsToRemove, changedJavaPaths);
			}
		} else {
			final int flags = delta.getFlags();
			if ((flags & IResourceDelta.MOVED_FROM) == IResourceDelta.MOVED_FROM) {
				if (rootFolder == null) {
					final IProject project = delta.getResource().getProject();
					// make certain this is a J2EE project
					if (ModuleCoreNature.getModuleCoreNature(project) != null) {
						IVirtualComponent c = ComponentCore.createComponent(project);
						rootFolder = c.getRootFolder();
						sourceToRuntime = getResourceMappings(project);
					} else {
						// not a J2EE project
						return;
					}
				}
				final IPath movedFrom = delta.getMovedFromPath().removeFirstSegments(1);
				if (changedJavaPaths.contains(movedFrom)) {
					// don't update renamed Java src paths
					return;
				}
				final IPath movedTo = delta.getFullPath().removeFirstSegments(1);
				final IPath runtimePath = (IPath) sourceToRuntime.get(movedFrom);
				// does the old path have a virtual component mapping?
				if (runtimePath != null) {
					final IVirtualFolder folder = rootFolder.getFolder(runtimePath);
					// only add if the project relative paths are not equal (these can be equal when the root folder is mapped and the project is renamed)
					if (!movedFrom.equals(movedTo)) {
						pathsToRemove.add(new Object[]{movedFrom, folder});
						pathsToAdd.add(new Object[]{movedTo, folder});
					}
				}
			}
		}
	}
	
	private Map getResourceMappings(final IProject project){
		final Map sourceToRuntime = new HashMap();
		StructureEdit core = null;
		try {
			core = StructureEdit.getStructureEditForRead(project);
			final WorkbenchComponent component = core.getComponent();
			if (null != component) {
				final List currentResources = component.getResources();
				for (Iterator iter = currentResources.iterator(); iter.hasNext();) {
					final ComponentResource resource = (ComponentResource) iter.next();
					sourceToRuntime.put(resource.getSourcePath().makeRelative(), resource.getRuntimePath());
				}
			}
			return sourceToRuntime;
		} finally {
			if (core != null)
				core.dispose();
		}
	}

	/*
	 * Retrieves the IVirtualFolder to which Java src folders should be mapped
	 */
	private IVirtualFolder getDestinationFolder(final IVirtualComponent c) throws CoreException {
		final IVirtualFolder root = c.getRootFolder();
		if (J2EEProjectUtilities.isDynamicWebProject(c.getProject())) {
			// web projects map to WEB-INF/classes
			return root.getFolder(new Path(J2EEConstants.WEB_INF_CLASSES));
		}
		// all other J2EE project types (that are Java projects) map 
		// Java src folders to the project root
		return root;
	}
	
}
