/*******************************************************************************
 * 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.internal.archive;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
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.Path;
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.j2ee.internal.J2EEConstants;
import org.eclipse.jst.j2ee.internal.plugin.IJ2EEModuleConstants;
import org.eclipse.jst.j2ee.internal.plugin.J2EEPlugin;
import org.eclipse.jst.j2ee.internal.project.J2EEProjectUtilities;
import org.eclipse.jst.jee.archive.ArchiveOpenFailureException;
import org.eclipse.jst.jee.archive.ArchiveOptions;
import org.eclipse.jst.jee.archive.IArchive;
import org.eclipse.jst.jee.archive.IArchiveFactory;
import org.eclipse.jst.jee.archive.IArchiveResource;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualContainer;

public class ConnectorComponentArchiveLoadAdapter extends ComponentArchiveLoadAdapter {

	private int dotJavaLength = JavaEEArchiveUtilities.DOT_JAVA.length();

	private List alreadyIndexed = new ArrayList();

	private Map classesMap;

	private IFile knownDD;

	public static String[] knownLibExtensions = { IJ2EEModuleConstants.JAR_EXT,
			".zip", //$NON-NLS-1$
			".so", //$NON-NLS-1$
			".o", //$NON-NLS-1$
			".sl", //$NON-NLS-1$
			".dll", //$NON-NLS-1$
	};

	public ConnectorComponentArchiveLoadAdapter(IVirtualComponent vComponent) {
		this(vComponent, true);
	}

	public ConnectorComponentArchiveLoadAdapter(IVirtualComponent vComponent, boolean includeClasspathComponents) {
		super(vComponent, includeClasspathComponents);
		knownDD = vComponent.getRootFolder().getFile(J2EEConstants.RAR_DD_URI).getUnderlyingFile();
	}

	@Override
	public List<IArchiveResource> getArchiveResources() {
		if (shouldOptimize()) {
			attemptOptimization();
		}
		if (!membersOptimized) {
			addNestedJARsFromSourceRoots();
			aggregateSourceFiles();
		}
		return filesHolder.getFiles();
	}

	private void addNestedJARsFromSourceRoots() {
		IPackageFragmentRoot[] sourceRoots = J2EEProjectUtilities.getSourceContainers(vComponent.getProject());
		for (int i = 0; i < sourceRoots.length; i++) {
			IArchiveResource aFile;
			try {
				aFile = getNestedJar(sourceRoots[i]);
				if (null != aFile) {
					filesHolder.addFile(aFile);
				}
			} catch (JavaModelException e) {
				J2EEPlugin.logError(e);
			} catch (ArchiveOpenFailureException e) {
				J2EEPlugin.logError(e);
			}
		}
	}

	private IArchiveResource getNestedJar(IPackageFragmentRoot sourceRoot) throws JavaModelException, ArchiveOpenFailureException {
		IPath outputPath = sourceRoot.getRawClasspathEntry().getOutputLocation();
		if (outputPath == null) {
			IProject project = vComponent.getProject();
			try {
				if (project.hasNature(JavaCore.NATURE_ID)) {
					IJavaProject javaProject = JavaCore.create(project);
					outputPath = javaProject.getOutputLocation();
				}
			} catch (CoreException e) {
				J2EEPlugin.logError(e);
			}
			if (outputPath == null) {
				return null;
			}
		}

		IFolder javaOutputFolder = ResourcesPlugin.getWorkspace().getRoot().getFolder(outputPath);
		indexClassesForOutputFolder(javaOutputFolder);
		IContainer sourceContainer = (IContainer) sourceRoot.getResource();

		int sourceContainerSegmentCount = sourceContainer.getProjectRelativePath().segmentCount();
		boolean isModuleRoot = knownDD.getProjectRelativePath().toString().startsWith(sourceContainer.getProjectRelativePath().toString());
		Set iFilesSet = new HashSet();
		boolean foundJava = gatherFilesForJAR(iFilesSet, sourceContainer, isModuleRoot, false, sourceContainerSegmentCount);
		if (!isModuleRoot || foundJava) {
			List <IFile> iFilesList = Collections.list(Collections.enumeration(iFilesSet));
			for (int i = 0; i < iFilesList.size(); i++) {
				filesHolder.removeIFile(iFilesList.get(i));
			}
			IArchiveResource nestedArchive = createNestedArchive(iFilesList, sourceContainer, javaOutputFolder);
			return nestedArchive;
		}
		return null;
	}

	private boolean gatherFilesForJAR(Collection iFiles, IContainer current, boolean isModuleRoot, boolean foundJava, int sourceContainerSegmentCount) {
		IResource[] members = null;
		try {
			members = current.members();
		} catch (CoreException core) {
			// TODO
			// throw new ArchiveRuntimeException(core);
		}
		
		IContainer ddFolder = vComponent.getRootFolder().getFolder(J2EEConstants.META_INF).getUnderlyingFolder();

		boolean localFoundJava = foundJava;
		if(members != null){
			for (int i = 0; i < members.length; i++) {
				IResource res = members[i];
				if (res.getType() == IResource.FOLDER) {
					if (!ddFolder.equals(res)) {//if it's not the dd folder
						localFoundJava = gatherFilesForJAR(iFiles, (IFolder) res, isModuleRoot, localFoundJava, sourceContainerSegmentCount) || localFoundJava;
					}
				} else {// it must be a file
					IFile srcFile = (IFile) res;
					if (belongsInNestedJAR(srcFile, isModuleRoot)) {
						if (JavaEEArchiveUtilities.isJava(srcFile)) {
							if (exportSource) {
								iFiles.add(srcFile); // don't need to check
								// duplicates here
							}
							String className = srcFile.getProjectRelativePath().removeFirstSegments(sourceContainerSegmentCount).toString();
							className = className.substring(0, className.length() - dotJavaLength);
							List classes = retrieveClasses(className);
							if (null != classes) {
								Iterator iterator = classes.iterator();
								while (iterator.hasNext()) {
									IFile clazz = (IFile) iterator.next();
									if (!iFiles.contains(clazz)) {
										// .class need to check for duplicates
										iFiles.add(clazz);
									}
								}
							}
						} else {
							if (!iFiles.contains(srcFile)) {
								// if it's not src, then it could be .class and need
								// to check for duplicates
								iFiles.add(srcFile);
							}
						}
						if (isModuleRoot)
							localFoundJava = localFoundJava || JavaEEArchiveUtilities.isJava(srcFile) || JavaEEArchiveUtilities.isClass(srcFile);
					}
				}
			}
		}
		return localFoundJava;
	}

	private IArchive createNestedArchive(List <IFile> files, IContainer sourceContainer, IFolder javaOutputFolder) throws ArchiveOpenFailureException {
		ConnectorComponentNestedJARArchiveLoadAdapter nestedLoader = new ConnectorComponentNestedJARArchiveLoadAdapter(files, sourceContainer, javaOutputFolder);
		ArchiveOptions nestedOptions = new ArchiveOptions();
		nestedOptions.setOption(ArchiveOptions.LOAD_ADAPTER, nestedLoader);
		IArchive nestedArchive = IArchiveFactory.INSTANCE.openArchive(nestedOptions);
		nestedArchive.setPath(new Path(computeUniqueArchiveURI(sourceContainer)));
		nestedArchive.setArchive(archive);
		return nestedArchive;
	}

	private String computeUniqueArchiveURI(IResource resource) {
		int increment = 0;
		String name = resource.getName();
		StringBuffer sb = null;
		do {
			sb = new StringBuffer(name.length() + 5);
			sb.append('_');
			sb.append(name);
			if (increment > 0)
				sb.append(increment);
			sb.append(IJ2EEModuleConstants.JAR_EXT);
			increment++;
		} while (filesHolder.contains(new Path(sb.toString())));
		return sb.toString();
	}

	private boolean belongsInNestedJAR(IFile iFile, boolean isModuleRoot) {
		if (isModuleRoot && isDeploymentDescriptor(iFile)) {
			return false;
		}
		for (int i = 0; i < knownLibExtensions.length; i++) {
			if (JavaEEArchiveUtilities.hasExtension(iFile, knownLibExtensions[i]))
				return false;
		}
		return true;
	}

	@Override
	protected boolean shouldInclude(IPath path) {
		String lastSegment = path.lastSegment();
		return null != lastSegment && !JavaEEArchiveUtilities.hasExtension(lastSegment, JavaEEArchiveUtilities.DOT_CLASS) && !JavaEEArchiveUtilities.hasExtension(lastSegment, JavaEEArchiveUtilities.DOT_JAVA);
	}

	/**
	 * Find all the .class files and index them so inner classes can be located.
	 */
	private void indexClassesForOutputFolder(IFolder javaOutputFolder) {
		if (null == javaOutputFolder || alreadyIndexed.contains(javaOutputFolder)) {
			return;
		}
		alreadyIndexed.add(javaOutputFolder);
		int segmentCount = javaOutputFolder.getProjectRelativePath().segmentCount();
		indexClasses(javaOutputFolder, segmentCount);
	}

	private void indexClasses(IResource resource, int javaOutputSegmentCount) {
		switch (resource.getType()) {
		case IResource.FILE:
			indexClass((IFile) resource, javaOutputSegmentCount);
			break;
		case IResource.FOLDER:
			try {
				IResource[] members = ((IFolder) resource).members();
				for (int i = 0; i < members.length; i++) {
					indexClasses(members[i], javaOutputSegmentCount);
				}
			} catch (CoreException e) {
				J2EEPlugin.logError(e);
			}
			break;
		}
	}

	private void indexClass(IFile iFile, int javaOutputSegmentCount) {
		if (!JavaEEArchiveUtilities.isClass(iFile))
			return;
		if (classesMap == null)
			classesMap = new HashMap();
		String name = iFile.getName();
		IPath relPath = iFile.getProjectRelativePath().removeFirstSegments(javaOutputSegmentCount);
		String key = relPath.toString();
		if (name.indexOf('$') != -1) {
			key = key.substring(0, key.indexOf('$'));
		} else {
			key = key.substring(0, key.indexOf('.'));
		}
		List inners = (List) classesMap.get(key);
		if (inners == null) {
			inners = new ArrayList(1);
			classesMap.put(key, inners);
		}
		inners.add(iFile);
	}

	public List retrieveClasses(String key) {
		if (classesMap == null)
			return null;
		return (List) classesMap.get(key);
	}

	private boolean isDeploymentDescriptor(IFile iFile) {
		return knownDD.equals(iFile);
	}
	
	@Override
	protected IPath getDefaultModelObjectPath() {
		return new Path(J2EEConstants.RAR_DD_URI);
	}
	
	@Override
	protected boolean shouldInclude(IVirtualContainer vContainer) {
		boolean isDDFolder = vComponent.getRootFolder().getFolder(J2EEConstants.META_INF).equals(vContainer);
		return isDDFolder || !inJavaSrc(vContainer);
	}
	
}
