/*******************************************************************************
 * Copyright (c) 2003, 2007 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.componentcore;

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

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jst.common.internal.modulecore.IClasspathDependencyComponent;
import org.eclipse.jst.common.internal.modulecore.IClasspathDependencyProvider;
import org.eclipse.jst.common.internal.modulecore.IClasspathDependencyReceiver;
import org.eclipse.jst.common.internal.modulecore.util.ManifestUtilities;
import org.eclipse.jst.common.jdt.internal.javalite.IJavaProjectLite;
import org.eclipse.jst.common.jdt.internal.javalite.JavaCoreLite;
import org.eclipse.jst.common.jdt.internal.javalite.JavaLiteUtilities;
import org.eclipse.jst.j2ee.classpathdep.ClasspathDependencyUtil;
import org.eclipse.jst.j2ee.commonarchivecore.internal.util.ArchiveUtil;
import org.eclipse.jst.j2ee.internal.J2EEConstants;
import org.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyVirtualComponent;
import org.eclipse.jst.j2ee.internal.common.J2EEDependencyListener;
import org.eclipse.jst.j2ee.internal.plugin.J2EEPlugin;
import org.eclipse.jst.j2ee.internal.project.J2EEProjectUtilities;
import org.eclipse.jst.j2ee.project.EarUtilities;
import org.eclipse.jst.j2ee.project.JavaEEProjectUtilities;
import org.eclipse.wst.common.componentcore.ComponentCore;
import org.eclipse.wst.common.componentcore.internal.builder.IDependencyGraph;
import org.eclipse.wst.common.componentcore.internal.resources.VirtualArchiveComponent;
import org.eclipse.wst.common.componentcore.internal.resources.VirtualComponent;
import org.eclipse.wst.common.componentcore.internal.resources.VirtualFolder;
import org.eclipse.wst.common.componentcore.internal.resources.VirtualReference;
import org.eclipse.wst.common.componentcore.internal.util.IComponentImplFactory;
import org.eclipse.wst.common.componentcore.internal.util.VirtualReferenceUtilities;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualFolder;
import org.eclipse.wst.common.componentcore.resources.IVirtualReference;

public class J2EEModuleVirtualComponent extends VirtualComponent implements IComponentImplFactory, IClasspathDependencyProvider, IClasspathDependencyReceiver {

	public static String GET_JAVA_REFS = "GET_JAVA_REFS"; //$NON-NLS-1$
	public static String GET_FUZZY_EAR_REFS = "GET_FUZZY_EAR_REFS"; //$NON-NLS-1$
	public static String GET_EXPANDED_LIB_REFS = "GET_EXPANDED_LIB_REFS"; //$NON-NLS-1$
	/**
	 * Use this value to retrieve references consisting of only META-INF/MANIFEST.MF classpath
	 * attributes.  Do this as follows:
	 * <code>
	 * IVirtualCompoment component = a virtual component
	 * Map<String, Object> onlyManifestRefs = new HashMap<String, Object>();
	 * onlyManifestRefs.put(IVirtualComponent.REQUESTED_REFERENCE_TYPE, J2EEModuleVirtualComponent.ONLY_MANIFEST_REFERENCES);
	 * IVirtualReference[] refs = component.getReferences(onlyManifestRefs); 
	 * </code> 
	 */
	public static String ONLY_MANIFEST_REFERENCES = "ONLY_MANIFEST_REFERENCES"; //$NON-NLS-1$
	
	private long depGraphModStamp;
	private long jeeModStamp;
	
	/**
	 * Accessors of this field should always use getHardReferences()
	 */
	private IVirtualReference[] hardReferences = null;
	private IVirtualReference[] javaReferences = null;
	private IVirtualReference[] parentEarManifestReferences = null;
	private IVirtualReference[] fuzzyEarManifestReferences = null;
	
	public J2EEModuleVirtualComponent() {
		super();
	}

	public J2EEModuleVirtualComponent(IProject aProject, IPath aRuntimePath) {
		super(aProject, aRuntimePath);
	}

	public IVirtualComponent createComponent(IProject aProject) {
		return new J2EEModuleVirtualComponent(aProject, new Path("/")); //$NON-NLS-1$
	}

	public IVirtualComponent createArchiveComponent(IProject aProject, String archiveLocation, IPath aRuntimePath) {
		return new J2EEModuleVirtualArchiveComponent(aProject, archiveLocation, aRuntimePath);
	}
	
	public IVirtualFolder createFolder(IProject aProject, IPath aRuntimePath) {
		return new VirtualFolder(aProject, aRuntimePath);
	}
	
	/**
	 * Retrieves all references except those computed dynamically from
	 * tagged Java classpath entries.
	 * @return IVirtualReferences for all non-Java classpath entry references.
	 */
	public IVirtualReference[] getNonJavaReferences() {
		return getReferences(false,false);
	}

	protected IVirtualReference[] getHardReferences() {
		if (!checkIfStillValid() || hardReferences == null) {
			Map<String, Object> map = new HashMap<String, Object>();
			map.put(REQUESTED_REFERENCE_TYPE, HARD_REFERENCES);
			hardReferences = super.getReferences(map);
		}
		return hardReferences;
	}

	protected static IVirtualReference[] getHardReferences(
			IVirtualComponent component) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put(REQUESTED_REFERENCE_TYPE, HARD_REFERENCES);
		return component.getReferences(map);
	}

	public IVirtualReference[] getJavaClasspathReferences() {
		//broken by cache
		//if (javaReferences == null || !checkIfStillValid())
			javaReferences = getJavaClasspathReferences(getHardReferences());
		return javaReferences;
	}

	@Override
	public IVirtualReference[] getReferences(Map<String, Object> options) {
		Object val = options.get(REQUESTED_REFERENCE_TYPE);
		if( val != null ) {
			if( HARD_REFERENCES.equals(val) || NON_DERIVED_REFERENCES.equals(val) || DISPLAYABLE_REFERENCES.equals(val)){
				return getHardReferences();
			} else if (ONLY_MANIFEST_REFERENCES.equals(val)){
				ArrayList<IVirtualReference> all = new ArrayList<IVirtualReference>();
				checkIfStillValid();
				cacheManifestReferences();
				all.addAll(Arrays.asList(parentEarManifestReferences));
				all.addAll(Arrays.asList(fuzzyEarManifestReferences));
				IVirtualReference[] refs = all.toArray(new IVirtualReference[all.size()]);
				VirtualReferenceUtilities.INSTANCE.ensureReferencesHaveNames(refs);
				return refs;
			}
		}
		Boolean objGetJavaRefs = (Boolean)options.get(GET_JAVA_REFS);
		Boolean objGetFuzzyEarRefs = (Boolean)options.get(GET_FUZZY_EAR_REFS);
		Boolean objGetExpandRefs = (Boolean)options.get(GET_EXPANDED_LIB_REFS);
		boolean getJavaRefs = objGetJavaRefs != null ? objGetJavaRefs.booleanValue() : true;
		boolean findFuzzyEARRefs = objGetFuzzyEarRefs != null ? objGetFuzzyEarRefs.booleanValue() : false;
		boolean getExpandRefs = objGetExpandRefs != null ? objGetExpandRefs.booleanValue() : false;
		
		IVirtualReference[] nonManifestRefs = getNonManifestRefs(getJavaRefs);
		if (val != null && FLATTENABLE_REFERENCES.equals(val)) {
			if (getExpandRefs) {
				return JavaEEProjectUtilities.getExpandedReferences(this, nonManifestRefs);
			}
			return nonManifestRefs;
		}
		ArrayList<IVirtualReference> all = new ArrayList<IVirtualReference>();
		all.addAll(Arrays.asList(nonManifestRefs));
		// retrieve the dynamic references specified via the MANIFEST.MF classpath
		cacheManifestReferences();
		ArrayList<IVirtualReference> dynamicRefs = new ArrayList<IVirtualReference>();
		dynamicRefs.addAll(Arrays.asList(parentEarManifestReferences));
		if (findFuzzyEARRefs)
			dynamicRefs.addAll(Arrays.asList(fuzzyEarManifestReferences));
		
		for (Iterator<IVirtualReference> iterator = dynamicRefs.iterator(); iterator.hasNext();) {
			IVirtualReference reference = iterator.next();
			IVirtualComponent dynamicComponent = reference.getReferencedComponent();
			boolean shouldInclude = true;
			for(IVirtualReference hardRef : getHardReferences()){
				if(hardRef.getReferencedComponent().equals(dynamicComponent)){
					shouldInclude = false;
					break;
				}
			}
			if (shouldInclude) {
				all.add(reference);
			}
		}
		IVirtualReference[] refs = all.toArray(new IVirtualReference[all.size()]);
		VirtualReferenceUtilities.INSTANCE.ensureReferencesHaveNames(refs);
		
		if (getExpandRefs) {
			return JavaEEProjectUtilities.getExpandedReferences(this, refs);
		}
		return refs;
	}

	@Override
	public IVirtualReference[] getReferences() {
		return getReferences(true, false);
	}

	public IVirtualReference[] getReferences(final boolean getJavaRefs, final boolean findFuzzyEARRefs) {
		Map<String, Object> options = new HashMap<String, Object>();
		options.put(GET_JAVA_REFS, new Boolean(getJavaRefs));
		options.put(GET_FUZZY_EAR_REFS, new Boolean(findFuzzyEARRefs));
		return getReferences(options);
	}

	/**
	 * Non-manifest references are hard references *OR* java classpath
	 * references
	 * 
	 * @return
	 */
	public IVirtualReference[] getNonManifestReferences() {
		Map<String, Object> options = new HashMap<String, Object>();
		options.put(IVirtualComponent.REQUESTED_REFERENCE_TYPE, IVirtualComponent.FLATTENABLE_REFERENCES);
		return getReferences(options);
	}
	
	@Deprecated
	public IVirtualReference[] getNonManifestReferences(final boolean getJavaRefs) {
		Map<String, Object> options = new HashMap<String, Object>();
		options.put(IVirtualComponent.REQUESTED_REFERENCE_TYPE, IVirtualComponent.FLATTENABLE_REFERENCES);
		options.put(GET_JAVA_REFS, new Boolean(getJavaRefs));
		return getReferences(options);
	}
	
	private IVirtualReference[] getNonManifestRefs(final boolean getJavaRefs) {
		ArrayList<IVirtualReference> allRefs = new ArrayList<IVirtualReference>();
		IVirtualReference[] hardRefs = getHardReferences();
		allRefs.addAll(Arrays.asList(hardRefs));
		if (getJavaRefs)
			allRefs.addAll(Arrays.asList(getJavaClasspathReferences(hardRefs)));
		return allRefs.toArray(new IVirtualReference[allRefs.size()]);
	}

	public static String[] getManifestClasspath(
			IVirtualComponent moduleComponent) {
		return ManifestUtilities.getManifestClasspath(moduleComponent,
				new Path(J2EEConstants.MANIFEST_URI));
	}

	public IVirtualReference[] getJavaClasspathReferences(
			IVirtualReference[] hardReferences) {
		final boolean isLegacyJ2EE = JavaEEProjectUtilities.isLegacyJ2EEComponent(this);
		final boolean isWebApp = JavaEEProjectUtilities.isDynamicWebComponent(this);

		final IProject project = getProject();
		final List cpRefs = new ArrayList();

		try {
			if (project == null || !project.isAccessible()
					|| !project.hasNature(JavaCoreLite.NATURE_ID)) {
				return new IVirtualReference[0];
			}

			final IJavaProjectLite javaProjectLite = JavaCoreLite.create(project);
			if (javaProjectLite == null)
				return new IVirtualReference[0];

			// retrieve all referenced classpath entries
			final Map referencedEntries = ClasspathDependencyUtil
					.getComponentClasspathDependencies(javaProjectLite,isLegacyJ2EE);

			if (referencedEntries.isEmpty())
				return new IVirtualReference[0];

			IVirtualReference[] innerHardReferences = hardReferences == null ? 
					getHardReferences() : hardReferences;
			final IPath[] hardRefPaths = new IPath[innerHardReferences.length];
			for (int j = 0; j < innerHardReferences.length; j++) {
				final IVirtualComponent comp = innerHardReferences[j].getReferencedComponent();
				if (comp.isBinary()) {
					hardRefPaths[j] = (IPath)comp.getAdapter(IPath.class);
				}
			}

			IContainer[] mappedClassFolders = null;
			final Iterator i = referencedEntries.keySet().iterator();
			while (i.hasNext()) {
				final IClasspathEntry entry = (IClasspathEntry) i.next();
				final IClasspathAttribute attrib = (IClasspathAttribute) referencedEntries
						.get(entry);
				final boolean isClassFolder = ClasspathDependencyUtil.isClassFolderEntry(entry);
				final IPath runtimePath = ClasspathDependencyUtil.getRuntimePath(attrib, isWebApp, isClassFolder);
				boolean add = true;
				final IPath entryLocation = ClasspathDependencyUtil.getEntryLocation(entry);
				if (entryLocation == null) {
					// unable to retrieve location for cp entry, do not
					// contribute as a virtual ref
					add = false;
				} else if (!isClassFolder) { // check hard archive refs
					for (int j = 0; j < hardRefPaths.length; j++) {
						if (entryLocation.equals(hardRefPaths[j])) {
							// entry resolves to same file as existing hard
							// reference, can skip
							add = false;
							break;
						}
					}
				} else { // check class folders mapped in component file as
					// class folders associated with mapped src folders
					if (mappedClassFolders == null) {
						List<IContainer> containers = JavaLiteUtilities
								.getJavaOutputContainers(this);
						mappedClassFolders = containers
								.toArray(new IContainer[containers.size()]);
					}
					for (int j = 0; j < mappedClassFolders.length; j++) {
						if (entryLocation.equals(mappedClassFolders[j]
								.getFullPath())) {
							// entry resolves to same file as existing class
							// folder mapping, skip
							add = false;
							break;
						}
					}
				}

				if (add && entryLocation != null) {
					String componentPath = null;
					ClasspathDependencyVirtualComponent entryComponent = null;
					/*
					 * if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT)
					 * { componentPath =
					 * VirtualArchiveComponent.CLASSPATHARCHIVETYPE; final
					 * IProject cpEntryProject =
					 * ResourcesPlugin.getWorkspace().getRoot
					 * ().getProject(entry.getPath().lastSegment());
					 * entryComponent = (VirtualArchiveComponent)
					 * ComponentCore.createArchiveComponent(cpEntryProject,
					 * componentPath); } else {
					 */
					componentPath = VirtualArchiveComponent.CLASSPATHARCHIVETYPE
							+ IPath.SEPARATOR + entryLocation.toPortableString();
					entryComponent = new ClasspathDependencyVirtualComponent(
							project, componentPath, isClassFolder);
					// }
					final IVirtualReference entryReference = ComponentCore
							.createReference(this, entryComponent, runtimePath);
					((VirtualReference) entryReference).setDerived(true);
					entryReference.setArchiveName(ClasspathDependencyUtil
							.getArchiveName(entry));
					cpRefs.add(entryReference);
				}
			}

		} catch (CoreException jme) {
			J2EEPlugin.logError(jme);
		}

		return (IVirtualReference[]) cpRefs.toArray(new IVirtualReference[cpRefs.size()]);
	}

	private void cacheManifestReferences() {
		if (parentEarManifestReferences == null
				|| fuzzyEarManifestReferences == null) {
			IVirtualReference[][] refs = calculateManifestReferences(this, true);
			parentEarManifestReferences = refs[0];
			fuzzyEarManifestReferences = refs[1];
		}
	}

	private static IVirtualReference[][] calculateManifestReferences(
			IVirtualComponent moduleComponent, boolean checkFuzzyRefs) {
		String[] manifestClasspath = getManifestClasspath(moduleComponent);
		IProject[] earProjects = EarUtilities
				.getReferencingEARProjects(moduleComponent.getProject());
		// Early aborts
		if (manifestClasspath == null || manifestClasspath.length == 0
				|| earProjects.length == 0) {
			return new IVirtualReference[][] { new IVirtualReference[0], new IVirtualReference[0] };
		}

		// Get our found cache going
		boolean[] foundRefAlready = new boolean[manifestClasspath.length];
		for (int i = 0; i < foundRefAlready.length; i++)
			foundRefAlready[i] = false;

		// Get the true parent references
		IProject firstEar = earProjects[earProjects.length - 1];
		ArrayList<IVirtualReference> tmp = cacheOneEarProjectManifestRefs(
				moduleComponent, firstEar, manifestClasspath, foundRefAlready);
		IVirtualReference[] parentEarManifestReferences = tmp
				.toArray(new IVirtualReference[tmp.size()]);

		ArrayList<IVirtualReference> dynamicReferences = new ArrayList<IVirtualReference>();
		// get the fuzzy references
		if (checkFuzzyRefs) {
			if (earProjects.length > 1) {
				for (int earIndex = earProjects.length - 2; earIndex > -1; earIndex--) {
					tmp = cacheOneEarProjectManifestRefs(moduleComponent,
							firstEar, manifestClasspath, foundRefAlready);
					dynamicReferences.addAll(tmp);
				}
			}
		}
		IVirtualReference[] fuzzyEarManifestReferences = dynamicReferences
				.toArray(new IVirtualReference[dynamicReferences.size()]);

		// return our two creatures
		return new IVirtualReference[][] { parentEarManifestReferences,
				fuzzyEarManifestReferences };
	}

	protected static ArrayList<IVirtualReference> cacheOneEarProjectManifestRefs(
			IVirtualComponent moduleComponent, IProject earProject,
			String[] manifestClasspath, boolean[] foundRefAlready) {
		ArrayList<IVirtualReference> dynamicReferences = new ArrayList<IVirtualReference>();

		IVirtualReference foundRef = null;
		String earArchiveURI = null; // The URI for this archive in the EAR
		boolean simplePath = false;
		IVirtualReference[] earRefs = null;
		IVirtualComponent tempEARComponent = ComponentCore
				.createComponent(earProject);
		IVirtualReference[] tempEarRefs = tempEARComponent.getReferences();
		for (int j = 0; j < tempEarRefs.length && earRefs == null; j++) {
			if (tempEarRefs[j].getReferencedComponent().equals(moduleComponent)) {
				earRefs = tempEarRefs;
				foundRef = tempEarRefs[j];
				earArchiveURI = foundRef.getArchiveName();
				simplePath = earArchiveURI != null ? earArchiveURI
						.lastIndexOf("/") == -1 : true; //$NON-NLS-1$
			}
		}
		if (null != earRefs) {
			for (int manifestIndex = 0; manifestIndex < manifestClasspath.length; manifestIndex++) {
				boolean found = false;
				if (foundRefAlready != null && foundRefAlready[manifestIndex]) {
					continue;
				}
				for (int j = 0; j < earRefs.length && !found; j++) {
					if (foundRef != earRefs[j]) {
						String archiveName = earRefs[j].getArchiveName();
						if (null != archiveName) {
							boolean shouldAdd = false;
							String manifestEntryString = manifestClasspath[manifestIndex];
							if (manifestEntryString != null) {
								IPath manifestPath = new Path(manifestEntryString);
								manifestEntryString = manifestPath
										.toPortableString();
							}

							if (simplePath && manifestEntryString != null
									&& manifestEntryString.lastIndexOf("/") == -1) { //$NON-NLS-1$
								shouldAdd = archiveName.equals(manifestEntryString);
							} else {
								String earRelativeURI = ArchiveUtil
										.deriveEARRelativeURI(manifestEntryString,
												earArchiveURI);
								if (null != earRelativeURI) {
									IPath earRefPath = earRefs[j].getRuntimePath().makeRelative();
									shouldAdd = earRelativeURI.equals(earRefPath.append(archiveName).toString());
								}
							}

							if (shouldAdd) {
								if (foundRefAlready != null) {
									foundRefAlready[manifestIndex] = true;
								}
								found = true;
								IVirtualComponent dynamicComponent = earRefs[j].getReferencedComponent();
								IVirtualReference dynamicReference = ComponentCore.createReference(moduleComponent,dynamicComponent);
								((VirtualReference) dynamicReference).setDerived(true);
								dynamicReferences.add(dynamicReference);
							}
						}
					}
				}
			}
		}
		return dynamicReferences;
	}

	public static List getManifestReferences(IVirtualComponent moduleComponent,
			IVirtualReference[] hardReferences) {
		return getManifestReferences(moduleComponent, hardReferences, false);
	}

	public static List getManifestReferences(IVirtualComponent moduleComponent,
			IVirtualReference[] hardReferences, boolean findFuzzyEARRefs) {
		IVirtualReference[][] refs = calculateManifestReferences(
				moduleComponent, findFuzzyEARRefs);
		ArrayList<IVirtualReference> tmp = new ArrayList<IVirtualReference>();
		tmp.addAll(Arrays.asList(refs[0]));
		if (findFuzzyEARRefs)
			tmp.addAll(Arrays.asList(refs[1]));
		return tmp;
	}

	private boolean checkIfStillValid() {
		boolean valid = IDependencyGraph.INSTANCE.getModStamp() == depGraphModStamp;
		valid = valid && J2EEDependencyListener.INSTANCE.getModStamp() == jeeModStamp;
		if (!valid) {
			clearCache();
		}
		return valid;
	}

	@Override
	protected void clearCache() {
		super.clearCache();
		depGraphModStamp = IDependencyGraph.INSTANCE.getModStamp();
		jeeModStamp = J2EEDependencyListener.INSTANCE.getModStamp();
		hardReferences = null;
		javaReferences = null;
		parentEarManifestReferences = null;
		fuzzyEarManifestReferences = null;
	}

	public boolean canReceiveClasspathDependencies() {
		return J2EEProjectUtilities.isDynamicWebProject(getProject());
	}

	public IPath getClasspathFolderPath(IClasspathDependencyComponent component) {
		if( J2EEProjectUtilities.isDynamicWebProject(getProject())) {
			return new Path(J2EEConstants.WEB_INF_LIB).makeAbsolute();
		}
		return new Path("/"); //$NON-NLS-1$
	}
}
