/*******************************************************************************
 * Copyright (c) 2003, 2006 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.common.classpath;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.resources.IFile;
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.IAccessRule;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.core.ClasspathEntry;
import org.eclipse.jdt.internal.core.JavaProject;
import org.eclipse.jdt.internal.core.util.Util;
import org.eclipse.jem.util.emf.workbench.ProjectUtilities;
import org.eclipse.jem.util.logger.proxy.Logger;
import org.eclipse.jst.common.jdt.internal.classpath.ClasspathDecorations;
import org.eclipse.jst.common.jdt.internal.classpath.ClasspathDecorationsManager;
import org.eclipse.jst.j2ee.internal.common.J2EECommonMessages;
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.internal.builder.DependencyGraphManager;
import org.eclipse.wst.common.componentcore.internal.resources.VirtualArchiveComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualReference;

/**
 * This classpath container is based on the Component references; not the manifest entries. Other
 * mechanisms are in place to ensure that the component references are updated when the manifest is
 * updated, and also to make sure the manifest is updated when the component references are updated.
 * 
 */
public class J2EEComponentClasspathContainer implements IClasspathContainer {

	public static final String CONTAINER_ID = "org.eclipse.jst.j2ee.internal.module.container"; //$NON-NLS-1$
	public static final IPath CONTAINER_PATH = new Path(CONTAINER_ID);

	private static IPath WEBLIB = new Path("/WEB-INF/lib"); //$NON-NLS-1$
	
	private static ClasspathDecorationsManager decorationsManager = new ClasspathDecorationsManager(J2EEPlugin.PLUGIN_ID);

	public static ClasspathDecorationsManager getDecorationsManager() {
        return decorationsManager;
    }
	
	private IPath containerPath;
	private IJavaProject javaProject;
	private IClasspathEntry[] entries = new IClasspathEntry[0];
	private static Map keys = new Hashtable();
	private static Map previousSelves = new Hashtable();
	
	private class LastUpdate {
		private long dotClasspathModificationStamp = -1;
		private int refCount = 0;
		private boolean[] isBinary = new boolean[refCount];
		private IPath[] paths = new IPath[refCount];
	}

	private LastUpdate lastUpdate = new LastUpdate();

	public J2EEComponentClasspathContainer(IPath path, IJavaProject javaProject) {
		this.containerPath = path;
		this.javaProject = javaProject;
	}

	private boolean requiresUpdate() {
		IVirtualComponent component = ComponentCore.createComponent(javaProject.getProject());
		if (component == null) {
			return false;
		}
		
		IFile dotClasspath = javaProject.getProject().getFile(ProjectUtilities.DOT_CLASSPATH);
		long dotClasspathModificationStamp = dotClasspath.exists() ? dotClasspath.getModificationStamp() : 0;
		if(dotClasspathModificationStamp != lastUpdate.dotClasspathModificationStamp){
			return true;
		}
		
		IVirtualReference[] refs = component.getReferences();
		IVirtualComponent comp = null;

		// avoid updating the container if references haven't changed
		if (refs.length == lastUpdate.refCount) {
			for (int i = 0; i < lastUpdate.refCount; i++) {
				comp = refs[i].getReferencedComponent();
				if (comp.isBinary() != lastUpdate.isBinary[i]) {
					return true;
				} else {
					IPath path = null;
					if (comp.isBinary()) {
						VirtualArchiveComponent archiveComp = (VirtualArchiveComponent) comp;
						java.io.File diskFile = archiveComp.getUnderlyingDiskFile();
						if (diskFile.exists())
							path = new Path(diskFile.getAbsolutePath());
						else {
							IFile iFile = archiveComp.getUnderlyingWorkbenchFile();
							path = iFile.getFullPath();
						}
					} else {
						path = comp.getProject().getFullPath();
					}
					if (!path.equals(lastUpdate.paths[i])) {
						return true;
					}
				}
			}
			return false;
		}
		return true;
	}
	
	private void update() {
		if(!javaProject.isOpen()){
			try {
				if(javaProject.getProject().exists() && javaProject.getProject().hasNature(JavaCore.NATURE_ID)){
					javaProject.open(null);
				} else {
					return;
				}
			} catch (JavaModelException e) {
				Logger.getLogger().logError(e);
			} catch (CoreException e) {
				//ignore 
				return;
			}
		}
		
		IVirtualComponent component = ComponentCore.createComponent(javaProject.getProject());
		Object key = keys.get(new Integer(javaProject.getProject().hashCode()));
		J2EEComponentClasspathContainer firstPreviousSelf = (J2EEComponentClasspathContainer)previousSelves.get(key);
		if (component == null) {
			return;
		}
		
		IFile dotClasspath = javaProject.getProject().getFile(ProjectUtilities.DOT_CLASSPATH);
		lastUpdate.dotClasspathModificationStamp = dotClasspath.exists() ? dotClasspath.getModificationStamp() : 0;
		
		IVirtualComponent comp = null;
		IVirtualReference ref = null;
		
		IVirtualReference[] refs = component.getReferences();
		List refsList = new ArrayList();
		Set refedComps = new HashSet();
		refedComps.add(component);
		for(int i = 0; i<refs.length;i++){
			refsList.add(refs[i]);
			refedComps.add(refs[i].getReferencedComponent());
		}
		for(int i=0; i< refsList.size(); i++){
			comp = ((IVirtualReference)refsList.get(i)).getReferencedComponent();
			if(comp.isBinary()){
				IVirtualReference [] binaryRefs = comp.getReferences();
				for(int j = 0; j<binaryRefs.length; j++){
					if(!refedComps.contains(binaryRefs[j].getReferencedComponent())){
						refsList.add(binaryRefs[j]);
						refedComps.add(binaryRefs[j].getReferencedComponent());
					}
				}
			}
		}
		
		lastUpdate.refCount = refsList.size();
		lastUpdate.isBinary = new boolean[lastUpdate.refCount];
		lastUpdate.paths = new IPath[lastUpdate.refCount];

		boolean isWeb = J2EEProjectUtilities.isDynamicWebProject(component.getProject());
		boolean shouldAdd = true;

		List entriesList = new ArrayList();

		try {
			IJavaProject javaProject = JavaCore.create(component.getProject());
			Set existingEntries = new HashSet();
			try {
				IClasspathContainer container = JavaCore.getClasspathContainer(CONTAINER_PATH, javaProject);
				List previousEntries = null;
				if(null != container){
					final IClasspathEntry[] containerEntries = container.getClasspathEntries();
					previousEntries = Arrays.asList(containerEntries);
				}
				existingEntries.addAll(Arrays.asList(javaProject.getResolvedClasspath(true)));
				if(null != previousEntries){
					existingEntries.removeAll(previousEntries);
				}
				if(firstPreviousSelf != null){
					existingEntries.removeAll(Arrays.asList(firstPreviousSelf.entries));
				}
				J2EEComponentClasspathContainer secondPreviousSelf = (J2EEComponentClasspathContainer)previousSelves.get(key);
				if(firstPreviousSelf != secondPreviousSelf && secondPreviousSelf != null){
					existingEntries.removeAll(Arrays.asList(secondPreviousSelf.entries));
				}
				
				existingEntries.removeAll(Arrays.asList(entries));
			
			} catch (JavaModelException e) {
				Logger.getLogger().logError(e);
			}
			//the default behavior is to always export these dependencies
			boolean exportEntries = true;
			boolean useJDTToControlExport = J2EEComponentClasspathContainerUtils.getDefaultUseEARLibrariesJDTExport();
			if(useJDTToControlExport){
				//if the default is not enabled, then check whether the container is being exported
				try{
					IClasspathEntry [] rawEntries = javaProject.getRawClasspath();
					for(int i=0;i<rawEntries.length; i++){
						IClasspathEntry entry = rawEntries[i];
						if(entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER){
							if(entry.getPath().equals(CONTAINER_PATH)){
								exportEntries = entry.isExported();
								break;
							}
						}
					}
				}  catch (JavaModelException e) {
					Logger.getLogger().logError(e);
				}
			}
			
			for (int i = 0; i < refsList.size(); i++) {
				ref = (IVirtualReference)refsList.get(i);
				comp = ref.getReferencedComponent();
				lastUpdate.isBinary[i] = comp.isBinary();
				shouldAdd = !(isWeb && ref.getRuntimePath().equals(WEBLIB)); 
				if (!shouldAdd) {
					continue;
				}
				if (comp.isBinary()) {
					VirtualArchiveComponent archiveComp = (VirtualArchiveComponent) comp;
					if (archiveComp.getArchiveType().equals(VirtualArchiveComponent.CLASSPATHARCHIVETYPE)) {
						// do not process components dynamically computed from the Java classpath
						continue;
					}
					java.io.File diskFile = archiveComp.getUnderlyingDiskFile();
					if (diskFile.exists()) {
						lastUpdate.paths[i] = new Path(diskFile.getAbsolutePath());
					} else {
						IFile iFile = archiveComp.getUnderlyingWorkbenchFile();
						lastUpdate.paths[i] = iFile.getFullPath();
					}
					if (!isAlreadyOnClasspath(existingEntries, lastUpdate.paths[i])) {
						ClasspathDecorations dec = decorationsManager.getDecorations( getPath().toString(), lastUpdate.paths[i].toString() );
						
						IPath srcpath = null;
				        IPath srcrootpath = null;
				        IClasspathAttribute[] attrs = {};
				        IAccessRule[] access = {};
						
				        if( dec != null ) {
				            srcpath = dec.getSourceAttachmentPath();
				            srcrootpath = dec.getSourceAttachmentRootPath();
				            attrs = dec.getExtraAttributes();
				        }
			        
				        entriesList.add(JavaCore.newLibraryEntry( lastUpdate.paths[i], srcpath, srcrootpath, access, attrs, exportEntries ));
					}
				} else {
					IProject project = comp.getProject();
					lastUpdate.paths[i] = project.getFullPath();
					if (!isAlreadyOnClasspath(existingEntries, lastUpdate.paths[i])) {
						entriesList.add(JavaCore.newProjectEntry(lastUpdate.paths[i], exportEntries));
					}
				}
			}
		} finally {
			entries = new IClasspathEntry[entriesList.size()];
			for (int i = 0; i < entries.length; i++) {
				entries[i] = (IClasspathEntry) entriesList.get(i);
			}
		}
		previousSelves.put(key, this);
	}

	public static void install(IPath containerPath, IJavaProject javaProject) {
		try{
			J2EEComponentClasspathUpdater.getInstance().pauseUpdates();
			Integer hashCode = new Integer(javaProject.getProject().hashCode());
			Object key = keys.get(hashCode);
			if(key == null){
				keys.put(hashCode, hashCode);
				key = hashCode;
			}
			final IJavaProject[] projects = new IJavaProject[]{javaProject};
			final J2EEComponentClasspathContainer container = new J2EEComponentClasspathContainer(containerPath, javaProject);
			container.update();
			final IClasspathContainer[] conts = new IClasspathContainer[]{container};
			try {
				JavaCore.setClasspathContainer(containerPath, projects, conts, null);
				previousSelves.put(key, container);
			} catch (JavaModelException e) {
				Logger.getLogger().log(e);
			}
		} finally {
			J2EEComponentClasspathUpdater.getInstance().resumeUpdates();
		}
	}

	public void refresh(boolean force){
		if(force || requiresUpdate()){
			install(containerPath, javaProject);
			if (J2EEComponentClasspathUpdater.shouldUpdateDependencyGraph())
			{
				// Update dependency graph
				DependencyGraphManager.getInstance().forceRefresh();
				// [202820]
				J2EEComponentClasspathUpdater.setUpdateDependencyGraph(false);
			}
		}
	}
	
	public void refresh() {
		refresh(false);
	}

	private boolean isUpdating = false;
	
	public IClasspathEntry[] getClasspathEntries() {
		if(!isUpdating){
			if(this != J2EEComponentClasspathContainerUtils.getInstalledEARLibrariesContainer(javaProject.getProject())){
				try {
					isUpdating = true;
					update();
				} finally{
					isUpdating = false;
				}
			}
		}
		return entries;
	}

	public String getDescription() {
		return J2EECommonMessages.J2EE_MODULE_CLASSPATH_CONTAINER_NAME;
	}

	public int getKind() {
		return K_APPLICATION;
	}

	public IPath getPath() {
		return containerPath;
	}

	/**
	 * Taken from {@link JavaProject#isOnClasspath(org.eclipse.core.resources.IResource)}
	 * 
	 * @param classpath
	 * @param newPath
	 * @return
	 */
	private static boolean isAlreadyOnClasspath(Set classpath, IPath newPath) {
		for (Iterator itr = classpath.iterator(); itr.hasNext();) {
			IClasspathEntry entry = (IClasspathEntry) itr.next();
			IPath entryPath = entry.getPath();
			if (entryPath.equals(newPath)) { // package fragment roots must match exactly entry
				// pathes (no exclusion there)
				return true;
			}
			if (entryPath.isPrefixOf(newPath) && !Util.isExcluded(newPath, ((ClasspathEntry) entry).fullInclusionPatternChars(), ((ClasspathEntry) entry).fullExclusionPatternChars(), false)) {
				return true;
			}
		}
		return false;
	}
}
