/*******************************************************************************
 * Copyright (c) 2000, 2011 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.ui.javadocexport;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;

import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;

public class JavadocWriter {

	private static final char PATH_SEPARATOR= '/'; // use forward slash for all platforms

	private final IJavaProject[] fJavaProjects;
	private final IPath fBasePath;

	/**
	 * Create a JavadocWriter.
	 * @param basePath The base path to which all path will be made relative (if
	 * possible). If <code>null</code>, paths are not made relative.
	 * @param projects
	 */
	public JavadocWriter(IPath basePath, IJavaProject[] projects) {
		fBasePath= basePath;
		fJavaProjects= projects;
	}

	public Element createXML(JavadocOptionsManager store) throws ParserConfigurationException {

		DocumentBuilder docBuilder= null;
		DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
		factory.setValidating(false);
		docBuilder= factory.newDocumentBuilder();
		Document document= docBuilder.newDocument();

		// Create the document
		Element project= document.createElement("project"); //$NON-NLS-1$
		document.appendChild(project);

		project.setAttribute("default", "javadoc"); //$NON-NLS-1$ //$NON-NLS-2$

		Element javadocTarget= document.createElement("target"); //$NON-NLS-1$
		project.appendChild(javadocTarget);
		javadocTarget.setAttribute("name", "javadoc"); //$NON-NLS-1$ //$NON-NLS-2$

		Element xmlJavadocDesc= document.createElement("javadoc"); //$NON-NLS-1$
		javadocTarget.appendChild(xmlJavadocDesc);

		if (!store.isFromStandard())
			xmlWriteDoclet(store, document, xmlJavadocDesc);
		else
			xmlWriteJavadocStandardParams(store, document, xmlJavadocDesc);

		return xmlJavadocDesc;
	}

	/**
	 * Writes the document to the given stream.
	 * It is the client's responsibility to close the output stream.
	 * @param javadocElement the XML element defining the Javadoc tags
	 * @param encoding the encoding to use
	 * @param outputStream the output stream
	 * @throws TransformerException thrown if writing fails
	 */
	public static void writeDocument(Element javadocElement, String encoding, OutputStream outputStream) throws TransformerException {

		// Write the document to the stream
		Transformer transformer=TransformerFactory.newInstance().newTransformer();
		transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
		transformer.setOutputProperty(OutputKeys.ENCODING, encoding);
		transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
		transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount","4"); //$NON-NLS-1$ //$NON-NLS-2$
		DOMSource source = new DOMSource(javadocElement.getOwnerDocument());
		StreamResult result = new StreamResult(new BufferedOutputStream(outputStream));
		transformer.transform(source, result);

	}

	//writes ant file, for now only worry about one project
	private void xmlWriteJavadocStandardParams(JavadocOptionsManager store, Document document, Element xmlJavadocDesc) throws DOMException {

		String destination= getPathString(Path.fromOSString(store.getDestination()));

		xmlJavadocDesc.setAttribute(store.DESTINATION, destination);
		xmlJavadocDesc.setAttribute(store.VISIBILITY, store.getAccess());
		String source= store.getSource();
		if (source.length() > 0 && !source.equals("-")) { //$NON-NLS-1$
			xmlJavadocDesc.setAttribute(store.SOURCE, store.getSource());
		}
		xmlJavadocDesc.setAttribute(store.USE, booleanToString(store.getBoolean("use"))); //$NON-NLS-1$
		xmlJavadocDesc.setAttribute(store.NOTREE, booleanToString(store.getBoolean("notree"))); //$NON-NLS-1$
		xmlJavadocDesc.setAttribute(store.NONAVBAR, booleanToString(store.getBoolean("nonavbar"))); //$NON-NLS-1$
		xmlJavadocDesc.setAttribute(store.NOINDEX, booleanToString(store.getBoolean("noindex"))); //$NON-NLS-1$
		xmlJavadocDesc.setAttribute(store.SPLITINDEX, booleanToString(store.getBoolean("splitindex"))); //$NON-NLS-1$
		xmlJavadocDesc.setAttribute(store.AUTHOR, booleanToString(store.getBoolean("author"))); //$NON-NLS-1$
		xmlJavadocDesc.setAttribute(store.VERSION, booleanToString(store.getBoolean("version"))); //$NON-NLS-1$
		xmlJavadocDesc.setAttribute(store.NODEPRECATEDLIST, booleanToString(store.getBoolean("nodeprecatedlist"))); //$NON-NLS-1$
		xmlJavadocDesc.setAttribute(store.NODEPRECATED, booleanToString(store.getBoolean("nodeprecated"))); //$NON-NLS-1$


		//set the packages and source files
		List<String> packages= new ArrayList<>();
		List<String> sourcefiles= new ArrayList<>();
		sortSourceElement(store.getSourceElements(), sourcefiles, packages);
		if (!packages.isEmpty())
			xmlJavadocDesc.setAttribute(store.PACKAGENAMES, toSeparatedList(packages));

		if (!sourcefiles.isEmpty())
			xmlJavadocDesc.setAttribute(store.SOURCEFILES, toSeparatedList(sourcefiles));

		xmlJavadocDesc.setAttribute(store.SOURCEPATH, getPathString(store.getSourcepath()));
		xmlJavadocDesc.setAttribute(store.CLASSPATH, getPathString(store.getClasspath()));

		String overview= store.getOverview();
		if (overview.length() > 0)
			xmlJavadocDesc.setAttribute(store.OVERVIEW, overview);

		String styleSheet= store.getStyleSheet();
		if (styleSheet.length() > 0)
			xmlJavadocDesc.setAttribute(store.STYLESHEETFILE, styleSheet);

		String title= store.getTitle();
		if (title.length() > 0)
			xmlJavadocDesc.setAttribute(store.TITLE, title);


		String vmArgs= store.getVMParams();
		String additionalArgs= store.getAdditionalParams();
		if (vmArgs.length() + additionalArgs.length() > 0) {
			String str= vmArgs + ' ' + additionalArgs;
			xmlJavadocDesc.setAttribute(store.EXTRAOPTIONS, str);
		}

		for (String href : store.getHRefs()) {
			Element links= document.createElement("link"); //$NON-NLS-1$
			xmlJavadocDesc.appendChild(links);
			links.setAttribute(store.HREF, href);
		}
	}

	private void sortSourceElement(IJavaElement[] iJavaElements, List<String> sourcefiles, List<String> packages) {
		for (IJavaElement element : iJavaElements) {
			IPath p= element.getResource().getLocation();
			if (p == null)
				continue;

			if (element instanceof ICompilationUnit) {
				String relative= getPathString(p);
				sourcefiles.add(relative);
			} else if (element instanceof IPackageFragment) {
				packages.add(element.getElementName());
			}
		}
	}

	private String getPathString(IPath[] paths) {
		StringBuilder buf= new StringBuilder();

		for (IPath path : paths) {
			if (buf.length() != 0) {
				buf.append(File.pathSeparatorChar);
			}
			buf.append(getPathString(path));
		}

		if (buf.length() == 0) {
			buf.append('.');
		}
		return buf.toString();
	}

	private boolean hasSameDevice(IPath p1, IPath p2) {
		String dev= p1.getDevice();
		if (dev == null) {
			return p2.getDevice() == null;
		}
		return dev.equals(p2.getDevice());
	}

	//make the path relative to the base path
	private String getPathString(IPath fullPath) {
		if (fBasePath == null || !hasSameDevice(fullPath, fBasePath)) {
			return fullPath.toOSString();
		}
		int matchingSegments= fBasePath.matchingFirstSegments(fullPath);
		if (fBasePath.segmentCount() == matchingSegments) {
			return getRelativePath(fullPath, matchingSegments);
		}
		for (IJavaProject javaProject : fJavaProjects) {
			IProject proj= javaProject.getProject();
			IPath projLoc= proj.getLocation();
			if (projLoc != null && projLoc.segmentCount() <= matchingSegments && projLoc.isPrefixOf(fullPath)) {
				return getRelativePath(fullPath, matchingSegments);
			}
		}
		IPath workspaceLoc= ResourcesPlugin.getWorkspace().getRoot().getLocation();
		if (workspaceLoc.segmentCount() <= matchingSegments && workspaceLoc.isPrefixOf(fullPath)) {
			return getRelativePath(fullPath, matchingSegments);
		}
		return fullPath.toOSString();
	}

	private String getRelativePath(IPath fullPath, int matchingSegments) {
		StringBuilder res= new StringBuilder();
		int backSegments= fBasePath.segmentCount() - matchingSegments;
		while (backSegments > 0) {
			res.append(".."); //$NON-NLS-1$
			res.append(PATH_SEPARATOR);
			backSegments--;
		}
		int segCount= fullPath.segmentCount();
		for (int i= matchingSegments; i < segCount; i++) {
			if (i > matchingSegments) {
				res.append(PATH_SEPARATOR);
			}
			res.append(fullPath.segment(i));
		}
		return res.toString();
	}

	private void xmlWriteDoclet(JavadocOptionsManager store, Document document, Element xmlJavadocDesc) throws DOMException {

		//set the packages and source files
		List<String> packages= new ArrayList<>();
		List<String> sourcefiles= new ArrayList<>();
		sortSourceElement(store.getSourceElements(), sourcefiles, packages);
		if (!packages.isEmpty())
			xmlJavadocDesc.setAttribute(store.PACKAGENAMES, toSeparatedList(packages));

		if (!sourcefiles.isEmpty())
			xmlJavadocDesc.setAttribute(store.SOURCEFILES, toSeparatedList(sourcefiles));

		xmlJavadocDesc.setAttribute(store.SOURCEPATH, getPathString(store.getSourcepath()));
		xmlJavadocDesc.setAttribute(store.CLASSPATH, getPathString(store.getClasspath()));
		xmlJavadocDesc.setAttribute(store.VISIBILITY, store.getAccess());

		Element doclet= document.createElement("doclet"); //$NON-NLS-1$
		xmlJavadocDesc.appendChild(doclet);
		doclet.setAttribute(store.NAME, store.getDocletName());
		doclet.setAttribute(store.PATH, store.getDocletPath());

		String str= store.getOverview();
		if (str.length() > 0)
			xmlJavadocDesc.setAttribute(store.OVERVIEW, str);

		str= store.getAdditionalParams();
		if (str.length() > 0)
			xmlJavadocDesc.setAttribute(store.EXTRAOPTIONS, str);

	}

	private String toSeparatedList(List<String> packages) {
		StringBuilder buf= new StringBuilder();
		Iterator<String> iter= packages.iterator();
		int nAdded= 0;
		while (iter.hasNext()) {
			if (nAdded > 0) {
				buf.append(',');
			}
			nAdded++;
			String curr= iter.next();
			buf.append(curr);
		}
		return buf.toString();
	}

	private String booleanToString(boolean bool) {
		if (bool)
			return "true"; //$NON-NLS-1$
		else
			return "false"; //$NON-NLS-1$
	}

}
