/*
 * Copyright (C) 2015, Google Inc.
 * and other copyright owners as documented in the project's IP log.
 *
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Distribution License v1.0 which
 * accompanies this distribution, is reproduced below, and is
 * available at http://www.eclipse.org/org/documents/edl-v10.php
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 *
 * - Neither the name of the Eclipse Foundation, Inc. nor the
 *   names of its contributors may be used to endorse or promote
 *   products derived from this software without specific prior
 *   written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.eclipse.jgit.gitrepo;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.MessageFormat;
import java.util.ArrayList;
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.jgit.annotations.NonNull;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.gitrepo.RepoProject.CopyFile;
import org.eclipse.jgit.gitrepo.RepoProject.LinkFile;
import org.eclipse.jgit.gitrepo.RepoProject.ReferenceFile;
import org.eclipse.jgit.gitrepo.internal.RepoText;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Repository;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;

/**
 * Repo XML manifest parser.
 *
 * @see <a href="https://code.google.com/p/git-repo/">git-repo project page</a>
 * @since 4.0
 */
public class ManifestParser extends DefaultHandler {
	private final String filename;
	private final URI baseUrl;
	private final String defaultBranch;
	private final Repository rootRepo;
	private final Map<String, Remote> remotes;
	private final Set<String> plusGroups;
	private final Set<String> minusGroups;
	private final List<RepoProject> projects;
	private final List<RepoProject> filteredProjects;
	private final IncludedFileReader includedReader;

	private String defaultRemote;
	private String defaultRevision;
	private int xmlInRead;
	private RepoProject currentProject;

	/**
	 * A callback to read included xml files.
	 */
	public interface IncludedFileReader {
		/**
		 * Read a file from the same base dir of the manifest xml file.
		 *
		 * @param path
		 *            The relative path to the file to read
		 * @return the {@code InputStream} of the file.
		 * @throws GitAPIException
		 * @throws IOException
		 */
		public InputStream readIncludeFile(String path)
				throws GitAPIException, IOException;
	}

	/**
	 * Constructor for ManifestParser
	 *
	 * @param includedReader
	 *            a
	 *            {@link org.eclipse.jgit.gitrepo.ManifestParser.IncludedFileReader}
	 *            object.
	 * @param filename
	 *            a {@link java.lang.String} object.
	 * @param defaultBranch
	 *            a {@link java.lang.String} object.
	 * @param baseUrl
	 *            a {@link java.lang.String} object.
	 * @param groups
	 *            a {@link java.lang.String} object.
	 * @param rootRepo
	 *            a {@link org.eclipse.jgit.lib.Repository} object.
	 */
	public ManifestParser(IncludedFileReader includedReader, String filename,
			String defaultBranch, String baseUrl, String groups,
			Repository rootRepo) {
		this.includedReader = includedReader;
		this.filename = filename;
		this.defaultBranch = defaultBranch;
		this.rootRepo = rootRepo;
		this.baseUrl = normalizeEmptyPath(URI.create(baseUrl));

		plusGroups = new HashSet<>();
		minusGroups = new HashSet<>();
		if (groups == null || groups.length() == 0
				|| groups.equals("default")) { //$NON-NLS-1$
			// default means "all,-notdefault"
			minusGroups.add("notdefault"); //$NON-NLS-1$
		} else {
			for (String group : groups.split(",")) { //$NON-NLS-1$
				if (group.startsWith("-")) //$NON-NLS-1$
					minusGroups.add(group.substring(1));
				else
					plusGroups.add(group);
			}
		}

		remotes = new HashMap<>();
		projects = new ArrayList<>();
		filteredProjects = new ArrayList<>();
	}

	/**
	 * Read the xml file.
	 *
	 * @param inputStream
	 *            a {@link java.io.InputStream} object.
	 * @throws java.io.IOException
	 */
	public void read(InputStream inputStream) throws IOException {
		xmlInRead++;
		final XMLReader xr;
		try {
			xr = XMLReaderFactory.createXMLReader();
		} catch (SAXException e) {
			throw new IOException(JGitText.get().noXMLParserAvailable);
		}
		xr.setContentHandler(this);
		try {
			xr.parse(new InputSource(inputStream));
		} catch (SAXException e) {
			throw new IOException(RepoText.get().errorParsingManifestFile, e);
		}
	}

	/** {@inheritDoc} */
	@Override
	public void startElement(
			String uri,
			String localName,
			String qName,
			Attributes attributes) throws SAXException {
		if ("project".equals(qName)) { //$NON-NLS-1$
			if (attributes.getValue("name") == null) { //$NON-NLS-1$
				throw new SAXException(RepoText.get().invalidManifest);
			}
			currentProject = new RepoProject(
					attributes.getValue("name"), //$NON-NLS-1$
					attributes.getValue("path"), //$NON-NLS-1$
					attributes.getValue("revision"), //$NON-NLS-1$
					attributes.getValue("remote"), //$NON-NLS-1$
					attributes.getValue("groups")); //$NON-NLS-1$
			currentProject.setRecommendShallow(
				attributes.getValue("clone-depth")); //$NON-NLS-1$
		} else if ("remote".equals(qName)) { //$NON-NLS-1$
			String alias = attributes.getValue("alias"); //$NON-NLS-1$
			String fetch = attributes.getValue("fetch"); //$NON-NLS-1$
			String revision = attributes.getValue("revision"); //$NON-NLS-1$
			Remote remote = new Remote(fetch, revision);
			remotes.put(attributes.getValue("name"), remote); //$NON-NLS-1$
			if (alias != null)
				remotes.put(alias, remote);
		} else if ("default".equals(qName)) { //$NON-NLS-1$
			defaultRemote = attributes.getValue("remote"); //$NON-NLS-1$
			defaultRevision = attributes.getValue("revision"); //$NON-NLS-1$
		} else if ("copyfile".equals(qName)) { //$NON-NLS-1$
			if (currentProject == null)
				throw new SAXException(RepoText.get().invalidManifest);
			currentProject.addCopyFile(new CopyFile(
						rootRepo,
						currentProject.getPath(),
						attributes.getValue("src"), //$NON-NLS-1$
						attributes.getValue("dest"))); //$NON-NLS-1$
		} else if ("linkfile".equals(qName)) { //$NON-NLS-1$
			if (currentProject == null) {
				throw new SAXException(RepoText.get().invalidManifest);
			}
			currentProject.addLinkFile(new LinkFile(
						rootRepo,
						currentProject.getPath(),
						attributes.getValue("src"), //$NON-NLS-1$
						attributes.getValue("dest"))); //$NON-NLS-1$
		} else if ("include".equals(qName)) { //$NON-NLS-1$
			String name = attributes.getValue("name"); //$NON-NLS-1$
			if (includedReader != null) {
				try (InputStream is = includedReader.readIncludeFile(name)) {
					if (is == null) {
						throw new SAXException(
								RepoText.get().errorIncludeNotImplemented);
					}
					read(is);
				} catch (Exception e) {
					throw new SAXException(MessageFormat.format(
							RepoText.get().errorIncludeFile, name), e);
				}
			} else if (filename != null) {
				int index = filename.lastIndexOf('/');
				String path = filename.substring(0, index + 1) + name;
				try (InputStream is = new FileInputStream(path)) {
					read(is);
				} catch (IOException e) {
					throw new SAXException(MessageFormat.format(
							RepoText.get().errorIncludeFile, path), e);
				}
			}
		} else if ("remove-project".equals(qName)) { //$NON-NLS-1$
			String name = attributes.getValue("name"); //$NON-NLS-1$
			projects.removeIf((p) -> p.getName().equals(name));
		}
	}

	/** {@inheritDoc} */
	@Override
	public void endElement(
			String uri,
			String localName,
			String qName) throws SAXException {
		if ("project".equals(qName)) { //$NON-NLS-1$
			projects.add(currentProject);
			currentProject = null;
		}
	}

	/** {@inheritDoc} */
	@Override
	public void endDocument() throws SAXException {
		xmlInRead--;
		if (xmlInRead != 0)
			return;

		// Only do the following after we finished reading everything.
		Map<String, URI> remoteUrls = new HashMap<>();
		if (defaultRevision == null && defaultRemote != null) {
			Remote remote = remotes.get(defaultRemote);
			if (remote != null) {
				defaultRevision = remote.revision;
			}
			if (defaultRevision == null) {
				defaultRevision = defaultBranch;
			}
		}
		for (RepoProject proj : projects) {
			String remote = proj.getRemote();
			String revision = defaultRevision;
			if (remote == null) {
				if (defaultRemote == null) {
					if (filename != null) {
						throw new SAXException(MessageFormat.format(
								RepoText.get().errorNoDefaultFilename,
								filename));
					}
					throw new SAXException(RepoText.get().errorNoDefault);
				}
				remote = defaultRemote;
			} else {
				Remote r = remotes.get(remote);
				if (r != null && r.revision != null) {
					revision = r.revision;
				}
			}
			URI remoteUrl = remoteUrls.get(remote);
			if (remoteUrl == null) {
				String fetch = remotes.get(remote).fetch;
				if (fetch == null) {
					throw new SAXException(MessageFormat
							.format(RepoText.get().errorNoFetch, remote));
				}
				remoteUrl = normalizeEmptyPath(baseUrl.resolve(fetch));
				remoteUrls.put(remote, remoteUrl);
			}
			proj.setUrl(remoteUrl.resolve(proj.getName()).toString())
				.setDefaultRevision(revision);
		}

		filteredProjects.addAll(projects);
		removeNotInGroup();
		removeOverlaps();
	}

	static URI normalizeEmptyPath(URI u) {
		// URI.create("scheme://host").resolve("a/b") => "scheme://hosta/b"
		// That seems like bug https://bugs.openjdk.java.net/browse/JDK-4666701.
		// We workaround this by special casing the empty path case.
		if (u.getHost() != null && !u.getHost().isEmpty() &&
			(u.getPath() == null || u.getPath().isEmpty())) {
			try {
				return new URI(u.getScheme(),
					u.getUserInfo(), u.getHost(), u.getPort(),
						"/", u.getQuery(), u.getFragment()); //$NON-NLS-1$
			} catch (URISyntaxException x) {
				throw new IllegalArgumentException(x.getMessage(), x);
			}
		}
		return u;
	}

	/**
	 * Getter for projects.
	 *
	 * @return projects list reference, never null
	 */
	public List<RepoProject> getProjects() {
		return projects;
	}

	/**
	 * Getter for filterdProjects.
	 *
	 * @return filtered projects list reference, never null
	 */
	@NonNull
	public List<RepoProject> getFilteredProjects() {
		return filteredProjects;
	}

	/** Remove projects that are not in our desired groups. */
	void removeNotInGroup() {
		Iterator<RepoProject> iter = filteredProjects.iterator();
		while (iter.hasNext())
			if (!inGroups(iter.next()))
				iter.remove();
	}

	/** Remove projects that sits in a subdirectory of any other project. */
	void removeOverlaps() {
		Collections.sort(filteredProjects);
		Iterator<RepoProject> iter = filteredProjects.iterator();
		if (!iter.hasNext())
			return;
		RepoProject last = iter.next();
		while (iter.hasNext()) {
			RepoProject p = iter.next();
			if (last.isAncestorOf(p))
				iter.remove();
			else
				last = p;
		}
		removeNestedCopyAndLinkfiles();
	}

	private void removeNestedCopyAndLinkfiles() {
		for (RepoProject proj : filteredProjects) {
			List<CopyFile> copyfiles = new ArrayList<>(proj.getCopyFiles());
			proj.clearCopyFiles();
			for (CopyFile copyfile : copyfiles) {
				if (!isNestedReferencefile(copyfile)) {
					proj.addCopyFile(copyfile);
				}
			}
			List<LinkFile> linkfiles = new ArrayList<>(proj.getLinkFiles());
			proj.clearLinkFiles();
			for (LinkFile linkfile : linkfiles) {
				if (!isNestedReferencefile(linkfile)) {
					proj.addLinkFile(linkfile);
				}
			}
		}
	}

	boolean inGroups(RepoProject proj) {
		for (String group : minusGroups) {
			if (proj.inGroup(group)) {
				// minus groups have highest priority.
				return false;
			}
		}
		if (plusGroups.isEmpty() || plusGroups.contains("all")) { //$NON-NLS-1$
			// empty plus groups means "all"
			return true;
		}
		for (String group : plusGroups) {
			if (proj.inGroup(group))
				return true;
		}
		return false;
	}

	private boolean isNestedReferencefile(ReferenceFile referencefile) {
		if (referencefile.dest.indexOf('/') == -1) {
			// If the referencefile is at root level then it won't be nested.
			return false;
		}
		for (RepoProject proj : filteredProjects) {
			if (proj.getPath().compareTo(referencefile.dest) > 0) {
				// Early return as remaining projects can't be ancestor of this
				// referencefile config (filteredProjects is sorted).
				return false;
			}
			if (proj.isAncestorOf(referencefile.dest)) {
				return true;
			}
		}
		return false;
	}

	private static class Remote {
		final String fetch;
		final String revision;

		Remote(String fetch, String revision) {
			this.fetch = fetch;
			this.revision = revision;
		}
	}
}
