/*******************************************************************************
 * Copyright (c) 2000, 2005 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.jdt.internal.corext.javadoc;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

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.QualifiedName;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.Job;

import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;

import org.eclipse.jface.preference.IPreferenceStore;

import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IImportDeclaration;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;

import org.eclipse.jdt.internal.corext.CorextMessages;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;

import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jdt.ui.PreferenceConstants;

import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.JavaUIException;
import org.eclipse.jdt.internal.ui.JavaUIStatus;
import org.eclipse.jdt.internal.ui.actions.WorkbenchRunnableAdapter;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathSupport;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElement;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class JavaDocLocations {
	
	public static final String ARCHIVE_PREFIX= "jar:file:/"; //$NON-NLS-1$
	private static final String PREF_JAVADOCLOCATIONS= "org.eclipse.jdt.ui.javadoclocations"; //$NON-NLS-1$
	public static final String PREF_JAVADOCLOCATIONS_MIGRATED= "org.eclipse.jdt.ui.javadoclocations.migrated"; //$NON-NLS-1$

	
	private static final String NODE_ROOT= "javadoclocation"; //$NON-NLS-1$
	private static final String NODE_ENTRY= "location_01"; //$NON-NLS-1$
	private static final String NODE_PATH= "path"; //$NON-NLS-1$
	private static final String NODE_URL= "url"; //$NON-NLS-1$
	
	private static final QualifiedName PROJECT_JAVADOC= new QualifiedName(JavaUI.ID_PLUGIN, "project_javadoc_location"); //$NON-NLS-1$
	
	public static void migrateToClasspathAttributes() {
		final Map oldLocations= loadOldForCompatibility();
		if (oldLocations.isEmpty()) {
			IPreferenceStore preferenceStore= PreferenceConstants.getPreferenceStore();
			preferenceStore.setValue(PREF_JAVADOCLOCATIONS, ""); //$NON-NLS-1$
			preferenceStore.setValue(PREF_JAVADOCLOCATIONS_MIGRATED, true);
			return;
		}
		
		Job job= new Job(CorextMessages.JavaDocLocations_migratejob_name) { 
			protected IStatus run(IProgressMonitor monitor) {
				try {
					IWorkspaceRunnable runnable= new IWorkspaceRunnable() {
						public void run(IProgressMonitor pm) throws CoreException {
							updateClasspathEntries(oldLocations, pm);
							IPreferenceStore preferenceStore= PreferenceConstants.getPreferenceStore();
							preferenceStore.setValue(PREF_JAVADOCLOCATIONS, ""); //$NON-NLS-1$
							preferenceStore.setValue(PREF_JAVADOCLOCATIONS_MIGRATED, true);
						}
					};
					new WorkbenchRunnableAdapter(runnable).run(monitor);
				} catch (InvocationTargetException e) {
					JavaPlugin.log(e);
				} catch (InterruptedException e) {
					// should not happen, cannot cancel
				}
				return Status.OK_STATUS;
			}
		};
		job.schedule();
	}
	
	final static void updateClasspathEntries(Map oldLocationMap, IProgressMonitor monitor) throws JavaModelException {
		IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();
		IJavaProject[] javaProjects= JavaCore.create(root).getJavaProjects();
		try {
			monitor.beginTask(CorextMessages.JavaDocLocations_migrate_operation, javaProjects.length); 
			for (int i= 0; i < javaProjects.length; i++) {
				IJavaProject project= javaProjects[i];
				String projectJavadoc= (String) oldLocationMap.get(project.getPath());
				if (projectJavadoc != null) {
					try {
						setProjectJavadocLocation(project, projectJavadoc);
					} catch (CoreException e) {
						// ignore
					}
				}
				
				IClasspathEntry[] rawClasspath= project.getRawClasspath();
				boolean hasChange= false;
				for (int k= 0; k < rawClasspath.length; k++) {
					IClasspathEntry updated= getConvertedEntry(rawClasspath[k], project, oldLocationMap);
					if (updated != null) {
						rawClasspath[k]= updated;
						hasChange= true;
					}
				}
				if (hasChange) {
					project.setRawClasspath(rawClasspath, new SubProgressMonitor(monitor, 1));
				} else {
					monitor.worked(1);
				}
			}
		} finally {
			monitor.done();
		}
	}

	private static IClasspathEntry getConvertedEntry(IClasspathEntry entry, IJavaProject project, Map oldLocationMap) {
		IPath path= null;
		switch (entry.getEntryKind()) {
			case IClasspathEntry.CPE_SOURCE:
			case IClasspathEntry.CPE_PROJECT:
				return null;
			case IClasspathEntry.CPE_CONTAINER:
				convertContainer(entry, project, oldLocationMap);
				return null;
			case IClasspathEntry.CPE_LIBRARY:
				path= entry.getPath();
				break;
			case IClasspathEntry.CPE_VARIABLE:
				path= JavaCore.getResolvedVariablePath(entry.getPath());
				break;
			default:
				return null;
		}
		if (path == null) {
			return null;
		}
		IClasspathAttribute[] extraAttributes= entry.getExtraAttributes();
		for (int i= 0; i < extraAttributes.length; i++) {
			if (IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME.equals(extraAttributes[i].getName())) {
				return null;
			}
		}
		String libraryJavadocLocation= (String) oldLocationMap.get(path);
		if (libraryJavadocLocation != null) {
			CPListElement element= CPListElement.createFromExisting(entry, project);
			element.setAttribute(CPListElement.JAVADOC, libraryJavadocLocation);
			return element.getClasspathEntry();
		}
		return null;
	}

	private static void convertContainer(IClasspathEntry entry, IJavaProject project, Map oldLocationMap) {
		try {
			IClasspathContainer container= JavaCore.getClasspathContainer(entry.getPath(), project);
			if (container == null) {
				return;
			}
			
			IClasspathEntry[] entries= container.getClasspathEntries();
			boolean hasChange= false;
			for (int i= 0; i < entries.length; i++) {
				IClasspathEntry curr= entries[i];
				IClasspathEntry updatedEntry= getConvertedEntry(curr, project, oldLocationMap);
				if (updatedEntry != null) {
					entries[i]= updatedEntry;
					hasChange= true;
				}
			}
			if (hasChange) {
				BuildPathSupport.requestContainerUpdate(project, container, entries);
			}
		} catch (CoreException e) {
			// ignore
		}
	}

	/**
	 * Sets the Javadoc location for an archive with the given path.
	 */
	public static void setProjectJavadocLocation(IJavaProject project, URL url) {
		try {
			String location= url != null ? url.toExternalForm() : null;
			setProjectJavadocLocation(project, location);
		} catch (CoreException e) {
			JavaPlugin.log(e);
		}
	}
	
	private static void setProjectJavadocLocation(IJavaProject project, String url) throws CoreException {
		project.getProject().setPersistentProperty(PROJECT_JAVADOC, url);
	}
	
	public static URL getProjectJavadocLocation(IJavaProject project) {
		try {
			String prop= project.getProject().getPersistentProperty(PROJECT_JAVADOC);
			if (prop == null) {
				return null;
			}
			return new URL(prop);
		} catch (CoreException e) {
			JavaPlugin.log(e);
		} catch (MalformedURLException e) {
			JavaPlugin.log(e);
		}
		return null;
	}
	
	
	public static URL getLibraryJavadocLocation(IClasspathEntry entry) {
		if (entry == null) {
			throw new IllegalArgumentException("Entry must not be null"); //$NON-NLS-1$
		}
		
		int kind= entry.getEntryKind();
		if (kind != IClasspathEntry.CPE_LIBRARY && kind != IClasspathEntry.CPE_VARIABLE) {
			throw new IllegalArgumentException("Entry must be of kind CPE_LIBRARY or CPE_VARIABLE"); //$NON-NLS-1$
		}
		
		IClasspathAttribute[] extraAttributes= entry.getExtraAttributes();
		for (int i= 0; i < extraAttributes.length; i++) {
			IClasspathAttribute attrib= extraAttributes[i];
			if (IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME.equals(attrib.getName())) {
				try {
					return new URL(attrib.getValue());
				} catch (MalformedURLException e) {
					return null;
				}
			}
		}
		return null;
	}

	public static URL getJavadocBaseLocation(IJavaElement element) throws JavaModelException {	
		if (element.getElementType() == IJavaElement.JAVA_PROJECT) {
			return getProjectJavadocLocation((IJavaProject) element);
		}
		
		IPackageFragmentRoot root= JavaModelUtil.getPackageFragmentRoot(element);
		if (root == null) {
			return null;
		}

		if (root.getKind() == IPackageFragmentRoot.K_BINARY) {
			IClasspathEntry entry= root.getRawClasspathEntry();
			if (entry == null) {
				return null;
			}
			if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
				entry= getRealClasspathEntry(root.getJavaProject(), entry.getPath(), root.getPath());
				if (entry == null) {
					return null;
				}
			}
			return getLibraryJavadocLocation(entry);
		} else {
			return getProjectJavadocLocation(root.getJavaProject());
		}	
	}
	
	private static IClasspathEntry getRealClasspathEntry(IJavaProject jproject, IPath containerPath, IPath libPath) throws JavaModelException {
		IClasspathContainer container= JavaCore.getClasspathContainer(containerPath, jproject);
		if (container != null) {
			IClasspathEntry[] entries= container.getClasspathEntries();
			for (int i= 0; i < entries.length; i++) {
				IClasspathEntry curr= entries[i];
				IClasspathEntry resolved= JavaCore.getResolvedClasspathEntry(curr);
				if (resolved != null && libPath.equals(resolved.getPath())) {
					return curr; // return the real entry
				}
			}
		}
		return null; // not found
	}
	
	
	// loading for compatibility
	
	private static JavaUIException createException(Throwable t, String message) {
		return new JavaUIException(JavaUIStatus.createError(IStatus.ERROR, message, t));
	}	
	
	private static Map/*<Path, String>*/ loadOldForCompatibility() {
		HashMap resultingOldLocations= new HashMap();
		
		// in 3.0, the javadoc locations were stored as one big string in the preferences
		String string= PreferenceConstants.getPreferenceStore().getString(PREF_JAVADOCLOCATIONS);
		if (string != null && string.length() > 0) {
			byte[] bytes;
			try {
				bytes= string.getBytes("UTF-8"); //$NON-NLS-1$
			} catch (UnsupportedEncodingException e) {
				bytes= string.getBytes();
			}
			InputStream is= new ByteArrayInputStream(bytes);
			try {
				loadFromStream(new InputSource(is), resultingOldLocations);
				PreferenceConstants.getPreferenceStore().setValue(PREF_JAVADOCLOCATIONS, ""); //$NON-NLS-1$
				return resultingOldLocations;
			} catch (CoreException e) {
				JavaPlugin.log(e); // log but ignore
			} finally {
				try {
					is.close();
				} catch (IOException e) {
					// ignore
				}
			}
		}

		// in 2.1, the Javadoc locations were stored in a file in the meta data
		// note that it is wrong to use a stream reader with XML declaring to be UTF-8
		try {
			final String STORE_FILE= "javadoclocations.xml"; //$NON-NLS-1$
			File file= JavaPlugin.getDefault().getStateLocation().append(STORE_FILE).toFile();
			if (file.exists()) {
				Reader reader= null;
				try {
					reader= new FileReader(file);
					loadFromStream(new InputSource(reader), resultingOldLocations);
					file.delete(); // remove file after successful store
					return resultingOldLocations;
				} catch (IOException e) {
					JavaPlugin.log(e); // log but ignore
				} finally {
					try {
						if (reader != null) {
							reader.close();
						}
					} catch (IOException e) {}
				}
			}
		} catch (CoreException e) {
			JavaPlugin.log(e); // log but ignore
		}	
		
		// in 2.0, the Javadoc locations were stored as one big string in the persistent properties
		// note that it is wrong to use a stream reader with XML declaring to be UTF-8
		try {
			final QualifiedName QUALIFIED_NAME= new QualifiedName(JavaUI.ID_PLUGIN, "jdoclocation"); //$NON-NLS-1$
			
			IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();
			String xmlString= root.getPersistentProperty(QUALIFIED_NAME); 
			if (xmlString != null) { // only set when workspace is old
				Reader reader= new StringReader(xmlString);
				try {
					loadFromStream(new InputSource(reader), resultingOldLocations);
					root.setPersistentProperty(QUALIFIED_NAME, null); // clear property
					return resultingOldLocations;
				} finally {

					try {
						reader.close();
					} catch (IOException e) {
						// error closing reader: ignore
					}
				}
			}
		} catch (CoreException e) {
			JavaPlugin.log(e); // log but ignore
		}
		return resultingOldLocations;
	}
	
	private static void loadFromStream(InputSource inputSource, Map/*<Path, String>*/ oldLocations) throws CoreException {
		Element cpElement;
		try {
			DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			cpElement = parser.parse(inputSource).getDocumentElement();
		} catch (SAXException e) {
			throw createException(e, CorextMessages.JavaDocLocations_error_readXML); 
		} catch (ParserConfigurationException e) {
			throw createException(e, CorextMessages.JavaDocLocations_error_readXML); 
		} catch (IOException e) {
			throw createException(e, CorextMessages.JavaDocLocations_error_readXML); 
		}
		
		if (cpElement == null) return;
		if (!cpElement.getNodeName().equalsIgnoreCase(NODE_ROOT)) {
			return;
		}
		NodeList list= cpElement.getChildNodes();
		int length= list.getLength();
		for (int i= 0; i < length; ++i) {
			Node node= list.item(i);
			short type= node.getNodeType();
			if (type == Node.ELEMENT_NODE) {
				Element element= (Element) node;
				if (element.getNodeName().equalsIgnoreCase(NODE_ENTRY)) {
					String varPath = element.getAttribute(NODE_PATH);
					String varURL = element.getAttribute(NODE_URL);
					
					oldLocations.put(Path.fromPortableString(varPath), varURL);
				}
			}
		}
	}
		
	public static URL getJavadocLocation(IJavaElement element, boolean includeMemberReference) throws JavaModelException {
		URL baseLocation= getJavadocBaseLocation(element);
		if (baseLocation == null) {
			return null;
		}

		String urlString= baseLocation.toExternalForm();

		StringBuffer pathBuffer= new StringBuffer(urlString);
		if (!urlString.endsWith("/")) { //$NON-NLS-1$
			pathBuffer.append('/');
		}

		switch (element.getElementType()) {
			case IJavaElement.PACKAGE_FRAGMENT:
				appendPackageSummaryPath((IPackageFragment) element, pathBuffer);
				break;
			case IJavaElement.JAVA_PROJECT:
			case IJavaElement.PACKAGE_FRAGMENT_ROOT :
				appendIndexPath(pathBuffer);
				break;
			case IJavaElement.IMPORT_CONTAINER :
				element= element.getParent();
				// fall through
			case IJavaElement.COMPILATION_UNIT :
				IType mainType= ((ICompilationUnit) element).findPrimaryType();
				if (mainType == null) {
					return null;
				}
				appendTypePath(mainType, pathBuffer);
				break;
			case IJavaElement.CLASS_FILE :
				appendTypePath(((IClassFile) element).getType(), pathBuffer);
				break;
			case IJavaElement.TYPE :
				appendTypePath((IType) element, pathBuffer);
				break;
			case IJavaElement.FIELD :
				IField field= (IField) element;
				appendTypePath(field.getDeclaringType(), pathBuffer);
				if (includeMemberReference) {
					appendFieldReference(field, pathBuffer);
				}
				break;
			case IJavaElement.METHOD :
				IMethod method= (IMethod) element;
				appendTypePath(method.getDeclaringType(), pathBuffer);
				if (includeMemberReference) {
					appendMethodReference(method, pathBuffer);
				}
				break;
			case IJavaElement.INITIALIZER :
				appendTypePath(((IMember) element).getDeclaringType(), pathBuffer);
				break;
			case IJavaElement.IMPORT_DECLARATION :
				IImportDeclaration decl= (IImportDeclaration) element;

				if (decl.isOnDemand()) {
					IJavaElement cont= JavaModelUtil.findTypeContainer(element.getJavaProject(), Signature.getQualifier(decl.getElementName()));
					if (cont instanceof IType) {
						appendTypePath((IType) cont, pathBuffer);
					} else if (cont instanceof IPackageFragment) {
						appendPackageSummaryPath((IPackageFragment) cont, pathBuffer);
					}
				} else {
					IType imp= element.getJavaProject().findType(decl.getElementName());
					appendTypePath(imp, pathBuffer);
				}
				break;
			case IJavaElement.PACKAGE_DECLARATION :
				IJavaElement pack= element.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
				if (pack != null) {
					appendPackageSummaryPath((IPackageFragment) pack, pathBuffer);
				} else {
					return null;
				}
				break;
			default :
				return null;
		}

		try {
			return new URL(pathBuffer.toString());
		} catch (MalformedURLException e) {
			JavaPlugin.log(e);
		}
		return null;
	}	
		
	private static void appendPackageSummaryPath(IPackageFragment pack, StringBuffer buf) {
		String packPath= pack.getElementName().replace('.', '/');
		buf.append(packPath);
		buf.append("/package-summary.html"); //$NON-NLS-1$
	}
	
	private static void appendIndexPath(StringBuffer buf) {
		buf.append("index.html"); //$NON-NLS-1$
	}	
	
	private static void appendTypePath(IType type, StringBuffer buf) {
		IPackageFragment pack= type.getPackageFragment();
		String packPath= pack.getElementName().replace('.', '/');
		String typePath= JavaModelUtil.getTypeQualifiedName(type);
		buf.append(packPath);
		buf.append('/');
		buf.append(typePath);
		buf.append(".html"); //$NON-NLS-1$
	}		
		
	private static void appendFieldReference(IField field, StringBuffer buf) {
		buf.append('#');
		buf.append(field.getElementName());
	}
	
	private static void appendMethodReference(IMethod meth, StringBuffer buf) throws JavaModelException {
		buf.append('#');
		buf.append(meth.getElementName());	
		
		buf.append('(');
		String[] params= meth.getParameterTypes();
		IType declaringType= meth.getDeclaringType();
		boolean isVararg= Flags.isVarargs(meth.getFlags());
		int lastParam= params.length - 1;
		for (int i= 0; i <= lastParam; i++) {
			if (i != 0) {
				buf.append(", "); //$NON-NLS-1$
			}
			String curr= Signature.getTypeErasure(params[i]);
			String fullName= JavaModelUtil.getResolvedTypeName(curr, declaringType);
			if (fullName != null) {
				buf.append(fullName);
				int dim= Signature.getArrayCount(curr);
				if (i == lastParam && isVararg) {
					dim--;
				}
				while (dim > 0) {
					buf.append("[]"); //$NON-NLS-1$
					dim--;
				}
				if (i == lastParam && isVararg) {
					buf.append("..."); //$NON-NLS-1$
				}
			}
		}
		buf.append(')');
	}


}
