/**********************************************************************
 * Copyright (c) 2007, 2008 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:
 *    Igor Fedorenko & Fabrizio Giustina - Initial API and implementation
 **********************************************************************/
package org.eclipse.jst.server.tomcat.core.internal.wst;

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

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.util.URI;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jst.server.tomcat.core.internal.TomcatPlugin;
import org.eclipse.jst.server.tomcat.core.internal.Trace;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.common.componentcore.ComponentCore;
import org.eclipse.wst.common.componentcore.UnresolveableURIException;
import org.eclipse.wst.common.componentcore.internal.ComponentResource;
import org.eclipse.wst.common.componentcore.internal.ReferencedComponent;
import org.eclipse.wst.common.componentcore.internal.StructureEdit;
import org.eclipse.wst.common.componentcore.internal.WorkbenchComponent;
import org.eclipse.wst.common.componentcore.internal.impl.ModuleURIUtil;
import org.eclipse.wst.common.componentcore.internal.impl.PlatformURLModuleConnection;
import org.eclipse.wst.common.componentcore.internal.util.IModuleConstants;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.server.core.IModule;

/**
 * Temporary solution for https://bugs.eclipse.org/bugs/show_bug.cgi?id=103888
 */
public class ModuleTraverser {

	/**
	 * Facet type for EAR modules
	 */
    public static final String EAR_MODULE = IModuleConstants.JST_EAR_MODULE;

    /**
     * Facet type for Web modules
     */
    public static final String WEB_MODULE = IModuleConstants.JST_WEB_MODULE;

    /**
     * Facet type for utility modules
     */
    public static final String UTILITY_MODULE = IModuleConstants.JST_UTILITY_MODULE;

    /**
     * Name of the custom Java classpath entry attribute that is used to flag entries
     * which should be exposed as module dependencies via the virtual component API.
     */
	public static final String CLASSPATH_COMPONENT_DEPENDENCY = "org.eclipse.jst.component.dependency"; //$NON-NLS-1
    
	/**
	 * Name of the custom Java classpath entry attribute that is used to flag
	 * the resolved entries of classpath containers that should not be exposed
	 * via the virtual component API.
	 */
	public static final String CLASSPATH_COMPONENT_NON_DEPENDENCY = "org.eclipse.jst.component.nondependency"; //$NON-NLS-1
	
	/**
	 * Argument values that are used to select component dependency attribute type. 
	 */
	private static final int DEPENDECYATTRIBUTETYPE_DEPENDENCY_OR_NONDEPENDENCY = 0;
	private static final int DEPENDECYATTRIBUTETYPE_CLASSPATH_COMPONENT_DEPENDENCY = 1;
	private static final int DEPENDECYATTRIBUTETYPE_CLASSPATH_COMPONENT_NONDEPENDENCY = 2;

	/**
     * Scans the module using the specified visitor.
     * 
     * @param module module to traverse
     * @param visitor visitor to handle resources
     * @param monitor a progress monitor
     * @throws CoreException
     */
    public static void traverse(IModule module, IModuleVisitor visitor,
            IProgressMonitor monitor) throws CoreException {
        if (module == null || module.getModuleType() == null)
            return;

        String typeId = module.getModuleType().getId();
        IVirtualComponent component = ComponentCore.createComponent(module.getProject());

        if (component == null) {
            // can happen if project has been closed
            Trace.trace(Trace.WARNING, "Unable to create component for module "
                    + module.getName());
            return;
        }

        if (EAR_MODULE.equals(typeId)) {
            traverseEarComponent(component, visitor, monitor);
        } else if (WEB_MODULE.equals(typeId)) {
            traverseWebComponent(component, visitor, monitor);
        }
    }

    private static void traverseEarComponent(IVirtualComponent component,
            IModuleVisitor visitor, IProgressMonitor monitor)
            throws CoreException {
    	// Currently the JST Server portion of WTP may not depend on the JST Enterprise portion of WTP
/*        EARArtifactEdit earEdit = EARArtifactEdit
                .getEARArtifactEditForRead(component);
        if (earEdit != null) {
            IVirtualReference[] j2eeComponents = earEdit.getJ2EEModuleReferences();
            for (int i = 0; i < j2eeComponents.length; i++) {
                traverseWebComponent(
                        j2eeComponents[i].getReferencedComponent(), visitor,
                        monitor);
            }
            IVirtualReference[] jarComponents = earEdit.getUtilityModuleReferences();
            for (int i = 0; i < jarComponents.length; i++) {
                IVirtualReference jarReference = jarComponents[i];
                IVirtualComponent jarComponent = jarReference
                        .getReferencedComponent();
                IProject dependentProject = jarComponent.getProject();
                if (!dependentProject.hasNature(JavaCore.NATURE_ID))
                    continue;
                IJavaProject project = JavaCore.create(dependentProject);
                IClasspathEntry cpe = getClasspathEntry(project, jarComponent
                        .getRootFolder().getProjectRelativePath());
                visitor.visitEarResource(null, getOSPath(dependentProject,
                        project, cpe.getOutputLocation()));
            }
        }*/
        visitor.endVisitEarComponent(component);
    }

    private static void traverseWebComponent(IVirtualComponent component,
            IModuleVisitor visitor, IProgressMonitor monitor)
            throws CoreException {

        visitor.visitWebComponent(component);

        IProject proj = component.getProject();
        StructureEdit warStruct = StructureEdit.getStructureEditForRead(proj);
        try {
            WorkbenchComponent comp = warStruct.getComponent();
            if (comp == null) {
                Trace.trace(Trace.SEVERE,
                        "Error getting WorkbenchComponent from war project. IProject=\""
                                + proj + "\" StructureEdit=\"" + warStruct
                                + "\" WorkbenchComponent=\"" + comp + "\"");
                return;
            }
            traverseWebComponentLocalEntries(comp, visitor, monitor);

            // traverse referenced components
            List children = comp.getReferencedComponents();
            for (Iterator itor = children.iterator(); itor.hasNext();) {
                ReferencedComponent childRef = (ReferencedComponent) itor.next();
                IPath rtFolder = childRef.getRuntimePath();
                URI refHandle = childRef.getHandle();

                if (PlatformURLModuleConnection.CLASSPATH.equals(
                		refHandle.segment(ModuleURIUtil.ModuleURI.SUB_PROTOCOL_INDX))) {
                    IPath refPath = getResolvedPathForArchiveComponent(refHandle);
                    // If an archive component, add to list
                    if (refPath != null) {
                    	if (!refPath.isAbsolute()) {
                    		IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(refPath);
                    		IPath refPath2 = file.getLocation();
                    		if (refPath2 != null) {
                    			visitor.visitArchiveComponent(rtFolder, refPath2);
                    		}
                    		else {
                    			Trace.trace(Trace.WARNING, NLS.bind(
                    					"Could not get the location of a referenced component.  It may not exist.  Project={0}, Parent Component={1}, Referenced Component Path={2}",
                    					new Object[] { proj.getName(), comp.getName(), refPath}));
                    		}
                    	}
                    	else {
                    		visitor.visitArchiveComponent(rtFolder, refPath);
                    	}
                    }
                    else {
                    	// TODO Determine if any use case would arrive here.
                    }
                } else {
                    try {
                        WorkbenchComponent childCom = warStruct.findComponentByURI(refHandle);
                        if (childCom == null) {
                            continue;
                        }

                        traverseDependentEntries(visitor, rtFolder, childCom,
                                monitor);
                    } catch (UnresolveableURIException e) {
                        TomcatPlugin.log(e);
                    }
                }
            }
        } finally {
            warStruct.dispose();
        }

        visitor.endVisitWebComponent(component);
    }

    private static void traverseWebComponentLocalEntries(
            WorkbenchComponent comp, IModuleVisitor visitor,
            IProgressMonitor monitor) throws CoreException {
        IProject warProject = StructureEdit.getContainingProject(comp);
        if (warProject == null || !warProject.hasNature(JavaCore.NATURE_ID)) {
            return;
        }
        IJavaProject project = JavaCore.create(warProject);

        List res = comp.getResources();
        for (Iterator itorRes = res.iterator(); itorRes.hasNext();) {
            ComponentResource childComp = (ComponentResource) itorRes.next();
            IClasspathEntry cpe = getClasspathEntry(project, childComp.getSourcePath());
            if (cpe == null)
                continue;
            visitor.visitWebResource(childComp.getRuntimePath(), getOSPath(
                    warProject, project, cpe.getOutputLocation()));
        }

        // Include tagged classpath entries
        Map classpathDeps = getComponentClasspathDependencies(project, true);
        for (Iterator iterator = classpathDeps.keySet().iterator(); iterator.hasNext();) {
			IClasspathEntry entry = (IClasspathEntry)iterator.next();
			IClasspathAttribute attrib = (IClasspathAttribute)classpathDeps.get(entry);
			boolean isClassFolder = isClassFolderEntry(entry);
			String rtFolder = attrib.getValue();
			if (rtFolder == null) {
				if (isClassFolder) {
					rtFolder = "/WEB-INF/classes";
				} else {
					rtFolder = "/WEB-INF/lib";
				}
			} 
			IPath entryPath = entry.getPath();
			IResource entryRes = ResourcesPlugin.getWorkspace().getRoot().findMember(entryPath);
			if (entryRes != null) {
				entryPath = entryRes.getLocation();
			}
			// TODO Determine if different handling is needed for some use cases
			if (isClassFolder) {
				 visitor.visitWebResource(new Path(rtFolder), 
		                    getOSPath(warProject, project, entry.getPath()));
			} else {
				visitor.visitArchiveComponent(new Path(rtFolder), entryPath);				
			}
		}
    }

    private static void traverseDependentEntries(IModuleVisitor visitor,
            IPath runtimeFolder, WorkbenchComponent component,
            IProgressMonitor monitor) throws CoreException {
        IProject dependentProject = StructureEdit.getContainingProject(component);
        if (!dependentProject.hasNature(JavaCore.NATURE_ID))
            return;
        IJavaProject project = JavaCore.create(dependentProject);

        String name = component.getName(); // assume it is the same as URI

        // go thru all entries
        List res = component.getResources();
        for (Iterator itorRes = res.iterator(); itorRes.hasNext();) {
            ComponentResource childComp = (ComponentResource) itorRes.next();
            IPath rtPath = childComp.getRuntimePath();
            IClasspathEntry cpe = getClasspathEntry(project, childComp.getSourcePath());
            if (cpe == null)
                continue;
            visitor.visitDependentComponent(runtimeFolder.append(rtPath)
                    .append(name + ".jar"), getOSPath(dependentProject,
                    project, cpe.getOutputLocation()));
        }

        // Include tagged classpath entries
        Map classpathDeps = getComponentClasspathDependencies(project, false);
        for (Iterator iterator = classpathDeps.keySet().iterator(); iterator.hasNext();) {
			IClasspathEntry entry = (IClasspathEntry)iterator.next();
			boolean isClassFolder = isClassFolderEntry(entry);
			String rtFolder = null;
			if (isClassFolder) {
				rtFolder = "/";
			} else {
				rtFolder = "/WEB-INF/lib";
			}
			IPath entryPath = entry.getPath();
			IResource entryRes = ResourcesPlugin.getWorkspace().getRoot().findMember(entryPath);
			if (entryRes != null) {
				entryPath = entryRes.getLocation();
			}
			// TODO Determine if different handling is needed for some use cases
			if (isClassFolder) {
				 visitor.visitDependentComponent(runtimeFolder.append(rtFolder)
		                    .append(name + ".jar"), getOSPath(dependentProject,
		                    project, entry.getPath()));
			} else {
				visitor.visitArchiveComponent(new Path(rtFolder), entryPath);
			}
		}
    }

    private static IClasspathEntry getClasspathEntry(IJavaProject project,
            IPath sourcePath) throws JavaModelException {
        sourcePath = project.getPath().append(sourcePath);
        IClasspathEntry[] cp = project.getRawClasspath();
        for (int i = 0; i < cp.length; i++) {
            if (sourcePath.equals(cp[i].getPath()))
                return JavaCore.getResolvedClasspathEntry(cp[i]);
        }
        return null;
    }

    private static IPath getOSPath(IProject project, IJavaProject javaProject,
            IPath outputPath) throws JavaModelException {
        if (outputPath == null)
            outputPath = javaProject.getOutputLocation();
        // If we have the root of a project, return project location
        if (outputPath.segmentCount() == 1) {
        	return ResourcesPlugin.getWorkspace().getRoot().getProject(outputPath.lastSegment())
        			.getLocation();
        }
        // Otherwise return project folder location
        return ResourcesPlugin.getWorkspace().getRoot().getFolder(outputPath)
                .getLocation();
    }

    /*
     * Derived from J2EEProjectUtilities.getResolvedPathForArchiveComponent()
     */
	private static IPath getResolvedPathForArchiveComponent(URI uri) {

		String resourceType = uri.segment(1);
		URI contenturi = ModuleURIUtil.trimToRelativePath(uri, 2);
		String contentName = contenturi.toString();

		if (resourceType.equals("lib")) { //$NON-NLS-1$
			// module:/classpath/lib/D:/foo/foo.jar
			return Path.fromOSString(contentName);

		} else if (resourceType.equals("var")) { //$NON-NLS-1$

			// module:/classpath/var/<CLASSPATHVAR>/foo.jar
			String classpathVar = contenturi.segment(0);
			URI remainingPathuri = ModuleURIUtil.trimToRelativePath(contenturi, 1);
			String remainingPath = remainingPathuri.toString();

			String[] classpathvars = JavaCore.getClasspathVariableNames();
			boolean found = false;
			for (int i = 0; i < classpathvars.length; i++) {
				if (classpathVar.equals(classpathvars[i])) {
					found = true;
					break;
				}
			}
			if (found) {
				IPath path = JavaCore.getClasspathVariable(classpathVar);
				if (path != null) {
					URI finaluri = URI.createURI(path.toOSString() + IPath.SEPARATOR + remainingPath);
					return Path.fromOSString(finaluri.toString());
				}
			}
			Trace.trace(Trace.WARNING,
					NLS.bind("Tomcat publishing could not resolve dependency URI \"{0}\".  A value for classpath variable {1} was not found.", uri, classpathVar));
		}
		return null;
	}

	/*
	 * Derived from ClasspathDependencyUtil.getComponentClasspathDependencies()
	 */
	private static Map getComponentClasspathDependencies(final IJavaProject javaProject, final boolean isWebApp) throws CoreException {

		// get the raw entries
		final Map referencedRawEntries = getRawComponentClasspathDependencies(javaProject);
		final Map validRawEntries = new HashMap();

		// filter out non-valid referenced raw entries
		final Iterator i = referencedRawEntries.keySet().iterator();
		while (i.hasNext()) {
			final IClasspathEntry entry = (IClasspathEntry) i.next();
			final IClasspathAttribute attrib = (IClasspathAttribute) referencedRawEntries.get(entry);
			if (isValid(entry, attrib, isWebApp, javaProject.getProject())) {
				validRawEntries.put(entry, attrib);
			}
		}

		// if we have no valid raw entries, return empty map
		if (validRawEntries.isEmpty()) {
        	return Collections.EMPTY_MAP;
		}

		// XXX Would like to replace the code below with use of a public JDT API that returns
		// the raw IClasspathEntry for a given resolved IClasspathEntry (see see https://bugs.eclipse.org/bugs/show_bug.cgi?id=183995)
		// The code must currently leverage IPackageFragmentRoot to determine this
		// mapping and, because IPackageFragmentRoots do not maintain IClasspathEntry data, a prior
		// call is needed to getResolvedClasspath() and the resolved IClasspathEntries have to be stored in a Map from IPath-to-IClasspathEntry to
		// support retrieval using the resolved IPackageFragmentRoot
		
		// retrieve the resolved classpath
		final IClasspathEntry[] entries = javaProject.getResolvedClasspath(true);
		final Map pathToResolvedEntry = new HashMap();
		
		// store in a map from path to entry
		for (int j = 0; j < entries.length; j++) {
			pathToResolvedEntry.put(entries[j].getPath(), entries[j]);
		}

		final Map referencedEntries = new LinkedHashMap();
		
		// grab all IPackageFragmentRoots
		final IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots();
		for (int j = 0; j < roots.length; j++) {
			final IPackageFragmentRoot root = roots[j];
			final IClasspathEntry rawEntry = root.getRawClasspathEntry();
			
			// is the raw entry valid?
			IClasspathAttribute attrib = (IClasspathAttribute) validRawEntries.get(rawEntry);
			if (attrib == null) {
				continue;
			}
			
			final IPath pkgFragPath = root.getPath();
			final IClasspathEntry resolvedEntry = (IClasspathEntry) pathToResolvedEntry.get(pkgFragPath);
			final IClasspathAttribute resolvedAttrib = checkForComponentDependencyAttribute(resolvedEntry,
					DEPENDECYATTRIBUTETYPE_DEPENDENCY_OR_NONDEPENDENCY);
			// attribute for the resolved entry must either be unspecified or it must be the
			// dependency attribute for it to be included
			if (resolvedAttrib == null || resolvedAttrib.getName().equals(CLASSPATH_COMPONENT_DEPENDENCY)) {
				// filter out resolved entry if it doesn't pass the validation rules
				if (isValid(resolvedEntry, resolvedAttrib != null ? resolvedAttrib : attrib, isWebApp, javaProject.getProject())) {
					if (resolvedAttrib != null) {
						// if there is an attribute on the sub-entry, use that
						attrib = resolvedAttrib;
					}
					referencedEntries.put(resolvedEntry, attrib);
				}
			} 
		}
		
        return referencedEntries;
	}

	/*
	 * Derived from ClasspathDependencyUtil.getRawComponentClasspathDependencies()
	 */
	private static Map getRawComponentClasspathDependencies(final IJavaProject javaProject) throws CoreException {
		if (javaProject == null) {
			return Collections.EMPTY_MAP;
		}
		final Map referencedRawEntries = new HashMap();
		final IClasspathEntry[] entries = javaProject.getRawClasspath();
        for (int i = 0; i < entries.length; i++) {
            final IClasspathEntry entry = entries[i];
            final IClasspathAttribute attrib = checkForComponentDependencyAttribute(entry,
            		DEPENDECYATTRIBUTETYPE_CLASSPATH_COMPONENT_DEPENDENCY);
            if (attrib != null) {
            	referencedRawEntries.put(entry, attrib);
            }
        }
        return referencedRawEntries;
	}

	/*
	 * Derived from ClasspathDependencyUtil.checkForComponentDependencyAttribute()
	 */
	private static IClasspathAttribute checkForComponentDependencyAttribute(final IClasspathEntry entry, final int attributeType) {
		if (entry == null) {
			return null;
		}
	    final IClasspathAttribute[] attributes = entry.getExtraAttributes();
	    for (int i = 0; i < attributes.length; i++) {
	    	final IClasspathAttribute attribute = attributes[i];
	    	final String name = attribute.getName();
	    	if (name.equals(CLASSPATH_COMPONENT_DEPENDENCY)) {
	    		if (attributeType == DEPENDECYATTRIBUTETYPE_DEPENDENCY_OR_NONDEPENDENCY
	    				|| attributeType == DEPENDECYATTRIBUTETYPE_CLASSPATH_COMPONENT_DEPENDENCY) {
	    			return attribute;
	    		}
	    	} else if (name.equals(CLASSPATH_COMPONENT_NON_DEPENDENCY)) {
	    		if (attributeType == DEPENDECYATTRIBUTETYPE_DEPENDENCY_OR_NONDEPENDENCY
	    				|| attributeType == DEPENDECYATTRIBUTETYPE_CLASSPATH_COMPONENT_NONDEPENDENCY) {
	    			return attribute;
	    		}
	    	}
	    }
	    return null;
	}

	/*
	 * Derived from ClasspathDependencyValidator.validateVirtualComponentEntry()
	 */
	private static boolean isValid(final IClasspathEntry entry, final IClasspathAttribute attrib, boolean isWebApp, final IProject project) {
		int kind = entry.getEntryKind();
		boolean isClassFolder = isClassFolderEntry(entry);
		
		if (kind == IClasspathEntry.CPE_PROJECT || kind == IClasspathEntry.CPE_SOURCE) {
			return false;
		}

		String runtimePath = getRuntimePath(attrib, isWebApp, isClassFolder);
		if (!isWebApp) {
			if (!runtimePath.equals("../") && !runtimePath.equals("/")) {
				return false;
			}
			if (isClassFolder && !runtimePath.equals("/")) {
				return false;
			}
		}
		else {
			if (runtimePath != null && !runtimePath.equals("/WEB-INF/lib")
					&& !runtimePath.equals("/WEB-INF/classes")
					&& !runtimePath.equals("../")) {
				return false;
			}
			if (isClassFolder && !runtimePath.equals("/WEB-INF/classes")) {
				return false;
			}
		}
		return true;
	}
	
	/*
	 * Derived from ClasspathDependencyUtil.isClassFolderEntry()
	 */
	private static boolean isClassFolderEntry(final IClasspathEntry entry) {
		if (entry == null || entry.getEntryKind() != IClasspathEntry.CPE_LIBRARY) {
			return false;
		}
		// does the path refer to a file or a folder?
		final IPath entryPath = entry.getPath();
		IPath entryLocation = entryPath;
		final IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(entryPath);
		if (resource != null) {
			entryLocation = resource.getLocation();
		}
		boolean isFile = true; // by default, assume a jar file
		if (entryLocation.toFile().isDirectory()) {
			isFile = false;
		}
		return !isFile;
	}
	
	/*
	 * Derived from ClasspathDependencyUtil.getRuntimePath()
	 */
	private static String getRuntimePath(final IClasspathAttribute attrib, final boolean isWebApp, final boolean isClassFolder) {
    	if (attrib != null && !attrib.getName().equals(CLASSPATH_COMPONENT_DEPENDENCY)) {
    		return null;
    	}
    	if (attrib == null || attrib.getValue()== null || attrib.getValue().length() == 0) {
    		if (isWebApp) {
    			return isClassFolder ? "/WEB_INF/classes" : "WEB-INF/lib";
    		} else {
    			return isClassFolder ? "/" : "../";
    		}
    	}
    	return attrib.getValue();
	}
}
