/*
 * Copyright (C) 2012 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.api;

import java.io.Closeable;
import java.io.IOException;
import java.io.OutputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.MutableObjectId;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.PathFilterGroup;

/**
 * Create an archive of files from a named tree.
 * <p>
 * Examples (<code>git</code> is a {@link org.eclipse.jgit.api.Git} instance):
 * <p>
 * Create a tarball from HEAD:
 *
 * <pre>
 * ArchiveCommand.registerFormat("tar", new TarFormat());
 * try {
 * 	git.archive().setTree(db.resolve(&quot;HEAD&quot;)).setOutputStream(out).call();
 * } finally {
 * 	ArchiveCommand.unregisterFormat("tar");
 * }
 * </pre>
 * <p>
 * Create a ZIP file from master:
 *
 * <pre>
 * ArchiveCommand.registerFormat("zip", new ZipFormat());
 * try {
 *	git.archive().
 *		.setTree(db.resolve(&quot;master&quot;))
 *		.setFormat("zip")
 *		.setOutputStream(out)
 *		.call();
 * } finally {
 *	ArchiveCommand.unregisterFormat("zip");
 * }
 * </pre>
 *
 * @see <a href="http://git-htmldocs.googlecode.com/git/git-archive.html" >Git
 *      documentation about archive</a>
 * @since 3.1
 */
public class ArchiveCommand extends GitCommand<OutputStream> {
	/**
	 * Archival format.
	 *
	 * Usage:
	 *	Repository repo = git.getRepository();
	 *	T out = format.createArchiveOutputStream(System.out);
	 *	try {
	 *		for (...) {
	 *			format.putEntry(out, path, mode, repo.open(objectId));
	 *		}
	 *		out.close();
	 *	}
	 *
	 * @param <T>
	 *            type representing an archive being created.
	 */
	public static interface Format<T extends Closeable> {
		/**
		 * Start a new archive. Entries can be included in the archive using the
		 * putEntry method, and then the archive should be closed using its
		 * close method.
		 *
		 * @param s
		 *            underlying output stream to which to write the archive.
		 * @return new archive object for use in putEntry
		 * @throws IOException
		 *             thrown by the underlying output stream for I/O errors
		 */
		T createArchiveOutputStream(OutputStream s) throws IOException;

		/**
		 * Start a new archive. Entries can be included in the archive using the
		 * putEntry method, and then the archive should be closed using its
		 * close method. In addition options can be applied to the underlying
		 * stream. E.g. compression level.
		 *
		 * @param s
		 *            underlying output stream to which to write the archive.
		 * @param o
		 *            options to apply to the underlying output stream. Keys are
		 *            option names and values are option values.
		 * @return new archive object for use in putEntry
		 * @throws IOException
		 *             thrown by the underlying output stream for I/O errors
		 * @since 4.0
		 */
		T createArchiveOutputStream(OutputStream s, Map<String, Object> o)
				throws IOException;

		/**
		 * Write an entry to an archive.
		 *
		 * @param out
		 *            archive object from createArchiveOutputStream
		 * @param tree
		 *            the tag, commit, or tree object to produce an archive for
		 * @param path
		 *            full filename relative to the root of the archive (with
		 *            trailing '/' for directories)
		 * @param mode
		 *            mode (for example FileMode.REGULAR_FILE or
		 *            FileMode.SYMLINK)
		 * @param loader
		 *            blob object with data for this entry (null for
		 *            directories)
		 * @throws IOException
		 *             thrown by the underlying output stream for I/O errors
		 * @since 4.7
		 */
		void putEntry(T out, ObjectId tree, String path, FileMode mode,
				ObjectLoader loader) throws IOException;

		/**
		 * Filename suffixes representing this format (e.g.,
		 * { ".tar.gz", ".tgz" }).
		 *
		 * The behavior is undefined when suffixes overlap (if
		 * one format claims suffix ".7z", no other format should
		 * take ".tar.7z").
		 *
		 * @return this format's suffixes
		 */
		Iterable<String> suffixes();
	}

	/**
	 * Signals an attempt to use an archival format that ArchiveCommand
	 * doesn't know about (for example due to a typo).
	 */
	public static class UnsupportedFormatException extends GitAPIException {
		private static final long serialVersionUID = 1L;

		private final String format;

		/**
		 * @param format the problematic format name
		 */
		public UnsupportedFormatException(String format) {
			super(MessageFormat.format(JGitText.get().unsupportedArchiveFormat, format));
			this.format = format;
		}

		/**
		 * @return the problematic format name
		 */
		public String getFormat() {
			return format;
		}
	}

	private static class FormatEntry {
		final Format<?> format;
		/** Number of times this format has been registered. */
		final int refcnt;

		public FormatEntry(Format<?> format, int refcnt) {
			if (format == null)
				throw new NullPointerException();
			this.format = format;
			this.refcnt = refcnt;
		}
	}

	/**
	 * Available archival formats (corresponding to values for
	 * the --format= option)
	 */
	private static final ConcurrentMap<String, FormatEntry> formats =
			new ConcurrentHashMap<>();

	/**
	 * Replaces the entry for a key only if currently mapped to a given
	 * value.
	 *
	 * @param map a map
	 * @param key key with which the specified value is associated
	 * @param oldValue expected value for the key (null if should be absent).
	 * @param newValue value to be associated with the key (null to remove).
	 * @return true if the value was replaced
	 */
	private static <K, V> boolean replace(ConcurrentMap<K, V> map,
			K key, V oldValue, V newValue) {
		if (oldValue == null && newValue == null) // Nothing to do.
			return true;

		if (oldValue == null)
			return map.putIfAbsent(key, newValue) == null;
		else if (newValue == null)
			return map.remove(key, oldValue);
		else
			return map.replace(key, oldValue, newValue);
	}

	/**
	 * Adds support for an additional archival format.  To avoid
	 * unnecessary dependencies, ArchiveCommand does not have support
	 * for any formats built in; use this function to add them.
	 * <p>
	 * OSGi plugins providing formats should call this function at
	 * bundle activation time.
	 * <p>
	 * It is okay to register the same archive format with the same
	 * name multiple times, but don't forget to unregister it that
	 * same number of times, too.
	 * <p>
	 * Registering multiple formats with different names and the
	 * same or overlapping suffixes results in undefined behavior.
	 * TODO: check that suffixes don't overlap.
	 *
	 * @param name name of a format (e.g., "tar" or "zip").
	 * @param fmt archiver for that format
	 * @throws JGitInternalException
	 *              A different archival format with that name was
	 *              already registered.
	 */
	public static void registerFormat(String name, Format<?> fmt) {
		if (fmt == null)
			throw new NullPointerException();

		FormatEntry old, entry;
		do {
			old = formats.get(name);
			if (old == null) {
				entry = new FormatEntry(fmt, 1);
				continue;
			}
			if (!old.format.equals(fmt))
				throw new JGitInternalException(MessageFormat.format(
						JGitText.get().archiveFormatAlreadyRegistered,
						name));
			entry = new FormatEntry(old.format, old.refcnt + 1);
		} while (!replace(formats, name, old, entry));
	}

	/**
	 * Marks support for an archival format as no longer needed so its
	 * Format can be garbage collected if no one else is using it either.
	 * <p>
	 * In other words, this decrements the reference count for an
	 * archival format.  If the reference count becomes zero, removes
	 * support for that format.
	 *
	 * @param name name of format (e.g., "tar" or "zip").
	 * @throws JGitInternalException
	 *              No such archival format was registered.
	 */
	public static void unregisterFormat(String name) {
		FormatEntry old, entry;
		do {
			old = formats.get(name);
			if (old == null)
				throw new JGitInternalException(MessageFormat.format(
						JGitText.get().archiveFormatAlreadyAbsent,
						name));
			if (old.refcnt == 1) {
				entry = null;
				continue;
			}
			entry = new FormatEntry(old.format, old.refcnt - 1);
		} while (!replace(formats, name, old, entry));
	}

	private static Format<?> formatBySuffix(String filenameSuffix)
			throws UnsupportedFormatException {
		if (filenameSuffix != null)
			for (FormatEntry entry : formats.values()) {
				Format<?> fmt = entry.format;
				for (String sfx : fmt.suffixes())
					if (filenameSuffix.endsWith(sfx))
						return fmt;
			}
		return lookupFormat("tar"); //$NON-NLS-1$
	}

	private static Format<?> lookupFormat(String formatName) throws UnsupportedFormatException {
		FormatEntry entry = formats.get(formatName);
		if (entry == null)
			throw new UnsupportedFormatException(formatName);
		return entry.format;
	}

	private OutputStream out;
	private ObjectId tree;
	private String prefix;
	private String format;
	private Map<String, Object> formatOptions = new HashMap<>();
	private List<String> paths = new ArrayList<>();

	/** Filename suffix, for automatically choosing a format. */
	private String suffix;

	/**
	 * Constructor for ArchiveCommand
	 *
	 * @param repo
	 *            the {@link org.eclipse.jgit.lib.Repository}
	 */
	public ArchiveCommand(Repository repo) {
		super(repo);
		setCallable(false);
	}

	private <T extends Closeable> OutputStream writeArchive(Format<T> fmt) {
		try {
			try (TreeWalk walk = new TreeWalk(repo);
					RevWalk rw = new RevWalk(walk.getObjectReader());
					T outa = fmt.createArchiveOutputStream(out,
							formatOptions)) {
				String pfx = prefix == null ? "" : prefix; //$NON-NLS-1$
				MutableObjectId idBuf = new MutableObjectId();
				ObjectReader reader = walk.getObjectReader();

				RevObject o = rw.peel(rw.parseAny(tree));
				walk.reset(getTree(o));
				if (!paths.isEmpty()) {
					walk.setFilter(PathFilterGroup.createFromStrings(paths));
				}

				// Put base directory into archive
				if (pfx.endsWith("/")) { //$NON-NLS-1$
					fmt.putEntry(outa, o, pfx.replaceAll("[/]+$", "/"), //$NON-NLS-1$ //$NON-NLS-2$
							FileMode.TREE, null);
				}

				while (walk.next()) {
					String name = pfx + walk.getPathString();
					FileMode mode = walk.getFileMode(0);

					if (walk.isSubtree())
						walk.enterSubtree();

					if (mode == FileMode.GITLINK) {
						// TODO(jrn): Take a callback to recurse
						// into submodules.
						mode = FileMode.TREE;
					}

					if (mode == FileMode.TREE) {
						fmt.putEntry(outa, o, name + "/", mode, null); //$NON-NLS-1$
						continue;
					}
					walk.getObjectId(idBuf, 0);
					fmt.putEntry(outa, o, name, mode, reader.open(idBuf));
				}
				return out;
			} finally {
				out.close();
			}
		} catch (IOException e) {
			// TODO(jrn): Throw finer-grained errors.
			throw new JGitInternalException(
					JGitText.get().exceptionCaughtDuringExecutionOfArchiveCommand, e);
		}
	}

	/** {@inheritDoc} */
	@Override
	public OutputStream call() throws GitAPIException {
		checkCallable();

		Format<?> fmt;
		if (format == null)
			fmt = formatBySuffix(suffix);
		else
			fmt = lookupFormat(format);
		return writeArchive(fmt);
	}

	/**
	 * Set the tag, commit, or tree object to produce an archive for
	 *
	 * @param tree
	 *            the tag, commit, or tree object to produce an archive for
	 * @return this
	 */
	public ArchiveCommand setTree(ObjectId tree) {
		if (tree == null)
			throw new IllegalArgumentException();

		this.tree = tree;
		setCallable(true);
		return this;
	}

	/**
	 * Set string prefixed to filenames in archive
	 *
	 * @param prefix
	 *            string prefixed to filenames in archive (e.g., "master/").
	 *            null means to not use any leading prefix.
	 * @return this
	 * @since 3.3
	 */
	public ArchiveCommand setPrefix(String prefix) {
		this.prefix = prefix;
		return this;
	}

	/**
	 * Set the intended filename for the produced archive. Currently the only
	 * effect is to determine the default archive format when none is specified
	 * with {@link #setFormat(String)}.
	 *
	 * @param filename
	 *            intended filename for the archive
	 * @return this
	 */
	public ArchiveCommand setFilename(String filename) {
		int slash = filename.lastIndexOf('/');
		int dot = filename.indexOf('.', slash + 1);

		if (dot == -1)
			this.suffix = ""; //$NON-NLS-1$
		else
			this.suffix = filename.substring(dot);
		return this;
	}

	/**
	 * Set output stream
	 *
	 * @param out
	 *            the stream to which to write the archive
	 * @return this
	 */
	public ArchiveCommand setOutputStream(OutputStream out) {
		this.out = out;
		return this;
	}

	/**
	 * Set archive format
	 *
	 * @param fmt
	 *            archive format (e.g., "tar" or "zip"). null means to choose
	 *            automatically based on the archive filename.
	 * @return this
	 */
	public ArchiveCommand setFormat(String fmt) {
		this.format = fmt;
		return this;
	}

	/**
	 * Set archive format options
	 *
	 * @param options
	 *            archive format options (e.g., level=9 for zip compression).
	 * @return this
	 * @since 4.0
	 */
	public ArchiveCommand setFormatOptions(Map<String, Object> options) {
		this.formatOptions = options;
		return this;
	}

	/**
	 * Set an optional parameter path. without an optional path parameter, all
	 * files and subdirectories of the current working directory are included in
	 * the archive. If one or more paths are specified, only these are included.
	 *
	 * @param paths
	 *            file names (e.g <code>file1.c</code>) or directory names (e.g.
	 *            <code>dir</code> to add <code>dir/file1</code> and
	 *            <code>dir/file2</code>) can also be given to add all files in
	 *            the directory, recursively. Fileglobs (e.g. *.c) are not yet
	 *            supported.
	 * @return this
	 * @since 3.4
	 */
	public ArchiveCommand setPaths(String... paths) {
		this.paths = Arrays.asList(paths);
		return this;
	}

	private RevTree getTree(RevObject o)
			throws IncorrectObjectTypeException {
		final RevTree t;
		if (o instanceof RevCommit) {
			t = ((RevCommit) o).getTree();
		} else if (!(o instanceof RevTree)) {
			throw new IncorrectObjectTypeException(tree.toObjectId(),
					Constants.TYPE_TREE);
		} else {
			t = (RevTree) o;
		}
		return t;
	}

}
