/*
 * Copyright (C) 2013, 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.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.FIFORevQueue;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevTag;
import org.eclipse.jgit.revwalk.RevWalk;

/**
 * Command to find human-readable names of revisions.
 *
 * @see <a
 *      href="http://www.kernel.org/pub/software/scm/git/docs/git-name-rev.html"
 *      >Git documentation about name-rev</a>
 * @since 3.0
 */
public class NameRevCommand extends GitCommand<Map<ObjectId, String>> {
	/** Amount of slop to allow walking past the earliest requested commit. */
	private static final int COMMIT_TIME_SLOP = 60 * 60 * 24;

	/** Cost of traversing a merge commit compared to a linear history. */
	private static final int MERGE_COST = 65535;

	private static class NameRevCommit extends RevCommit {
		private String tip;
		private int distance;
		private long cost;

		private NameRevCommit(AnyObjectId id) {
			super(id);
		}

		private StringBuilder format() {
			StringBuilder sb = new StringBuilder(tip);
			if (distance > 0)
				sb.append('~').append(distance);
			return sb;
		}

		@Override
		public String toString() {
			StringBuilder sb = new StringBuilder(getClass().getSimpleName())
				.append('[');
			if (tip != null)
				sb.append(format());
			else
				sb.append((Object) null);
			sb.append(',').append(cost).append(']').append(' ')
				.append(super.toString()).toString();
			return sb.toString();
		}
	}

	private final RevWalk walk;
	private final List<String> prefixes;
	private final List<ObjectId> revs;
	private List<Ref> refs;
	private int mergeCost;

	/**
	 * Create a new name-rev command.
	 *
	 * @param repo
	 *            the {@link org.eclipse.jgit.lib.Repository}
	 */
	protected NameRevCommand(Repository repo) {
		super(repo);
		mergeCost = MERGE_COST;
		prefixes = new ArrayList<>(2);
		revs = new ArrayList<>(2);
		walk = new RevWalk(repo) {
			@Override
			public NameRevCommit createCommit(AnyObjectId id) {
				return new NameRevCommit(id);
			}
		};
	}

	/** {@inheritDoc} */
	@Override
	public Map<ObjectId, String> call() throws GitAPIException {
		try {
			Map<ObjectId, String> nonCommits = new HashMap<>();
			FIFORevQueue pending = new FIFORevQueue();
			if (refs != null) {
				for (Ref ref : refs)
					addRef(ref, nonCommits, pending);
			}
			addPrefixes(nonCommits, pending);
			int cutoff = minCommitTime() - COMMIT_TIME_SLOP;

			while (true) {
				NameRevCommit c = (NameRevCommit) pending.next();
				if (c == null)
					break;
				if (c.getCommitTime() < cutoff)
					continue;
				for (int i = 0; i < c.getParentCount(); i++) {
					NameRevCommit p = (NameRevCommit) walk.parseCommit(c.getParent(i));
					long cost = c.cost + (i > 0 ? mergeCost : 1);
					if (p.tip == null || compare(c.tip, cost, p.tip, p.cost) < 0) {
						if (i > 0) {
							p.tip = c.format().append('^').append(i + 1).toString();
							p.distance = 0;
						} else {
							p.tip = c.tip;
							p.distance = c.distance + 1;
						}
						p.cost = cost;
						pending.add(p);
					}
				}
			}

			Map<ObjectId, String> result =
				new LinkedHashMap<>(revs.size());
			for (ObjectId id : revs) {
				RevObject o = walk.parseAny(id);
				if (o instanceof NameRevCommit) {
					NameRevCommit c = (NameRevCommit) o;
					if (c.tip != null)
						result.put(id, simplify(c.format().toString()));
				} else {
					String name = nonCommits.get(id);
					if (name != null)
						result.put(id, simplify(name));
				}
			}

			setCallable(false);
			return result;
		} catch (IOException e) {
			throw new JGitInternalException(e.getMessage(), e);
		} finally {
			walk.close();
		}
	}

	/**
	 * Add an object to search for.
	 *
	 * @param id
	 *            object ID to add.
	 * @return {@code this}
	 * @throws org.eclipse.jgit.errors.MissingObjectException
	 *             the object supplied is not available from the object
	 *             database.
	 * @throws org.eclipse.jgit.api.errors.JGitInternalException
	 *             a low-level exception of JGit has occurred. The original
	 *             exception can be retrieved by calling
	 *             {@link java.lang.Exception#getCause()}.
	 */
	public NameRevCommand add(ObjectId id) throws MissingObjectException,
			JGitInternalException {
		checkCallable();
		try {
			walk.parseAny(id);
		} catch (MissingObjectException e) {
			throw e;
		} catch (IOException e) {
			throw new JGitInternalException(e.getMessage(), e);
		}
		revs.add(id.copy());
		return this;
	}

	/**
	 * Add multiple objects to search for.
	 *
	 * @param ids
	 *            object IDs to add.
	 * @return {@code this}
	 * @throws org.eclipse.jgit.errors.MissingObjectException
	 *             the object supplied is not available from the object
	 *             database.
	 * @throws org.eclipse.jgit.api.errors.JGitInternalException
	 *             a low-level exception of JGit has occurred. The original
	 *             exception can be retrieved by calling
	 *             {@link java.lang.Exception#getCause()}.
	 */
	public NameRevCommand add(Iterable<ObjectId> ids)
			throws MissingObjectException, JGitInternalException {
		for (ObjectId id : ids)
			add(id);
		return this;
	}

	/**
	 * Add a ref prefix to the set that results must match.
	 * <p>
	 * If an object matches multiple refs equally well, the first matching ref
	 * added with {@link #addRef(Ref)} is preferred, or else the first matching
	 * prefix added by {@link #addPrefix(String)}.
	 *
	 * @param prefix
	 *            prefix to add; the prefix must end with a slash
	 * @return {@code this}
	 */
	public NameRevCommand addPrefix(String prefix) {
		checkCallable();
		prefixes.add(prefix);
		return this;
	}

	/**
	 * Add all annotated tags under {@code refs/tags/} to the set that all
	 * results must match.
	 * <p>
	 * Calls {@link #addRef(Ref)}; see that method for a note on matching
	 * priority.
	 *
	 * @return {@code this}
	 * @throws JGitInternalException
	 *             a low-level exception of JGit has occurred. The original
	 *             exception can be retrieved by calling
	 *             {@link java.lang.Exception#getCause()}.
	 */
	public NameRevCommand addAnnotatedTags() {
		checkCallable();
		if (refs == null)
			refs = new ArrayList<>();
		try {
			for (Ref ref : repo.getRefDatabase()
					.getRefsByPrefix(Constants.R_TAGS)) {
				ObjectId id = ref.getObjectId();
				if (id != null && (walk.parseAny(id) instanceof RevTag))
					addRef(ref);
			}
		} catch (IOException e) {
			throw new JGitInternalException(e.getMessage(), e);
		}
		return this;
	}

	/**
	 * Add a ref to the set that all results must match.
	 * <p>
	 * If an object matches multiple refs equally well, the first matching ref
	 * added with {@link #addRef(Ref)} is preferred, or else the first matching
	 * prefix added by {@link #addPrefix(String)}.
	 *
	 * @param ref
	 *            ref to add.
	 * @return {@code this}
	 */
	public NameRevCommand addRef(Ref ref) {
		checkCallable();
		if (refs == null)
			refs = new ArrayList<>();
		refs.add(ref);
		return this;
	}

	NameRevCommand setMergeCost(int cost) {
		mergeCost = cost;
		return this;
	}

	private void addPrefixes(Map<ObjectId, String> nonCommits,
			FIFORevQueue pending) throws IOException {
		if (!prefixes.isEmpty()) {
			for (String prefix : prefixes)
				addPrefix(prefix, nonCommits, pending);
		} else if (refs == null)
			addPrefix(Constants.R_REFS, nonCommits, pending);
	}

	private void addPrefix(String prefix, Map<ObjectId, String> nonCommits,
			FIFORevQueue pending) throws IOException {
		for (Ref ref : repo.getRefDatabase().getRefsByPrefix(prefix))
			addRef(ref, nonCommits, pending);
	}

	private void addRef(Ref ref, Map<ObjectId, String> nonCommits,
			FIFORevQueue pending) throws IOException {
		if (ref.getObjectId() == null)
			return;
		RevObject o = walk.parseAny(ref.getObjectId());
		while (o instanceof RevTag) {
			RevTag t = (RevTag) o;
			nonCommits.put(o, ref.getName());
			o = t.getObject();
			walk.parseHeaders(o);
		}
		if (o instanceof NameRevCommit) {
			NameRevCommit c = (NameRevCommit) o;
			if (c.tip == null)
				c.tip = ref.getName();
			pending.add(c);
		} else if (!nonCommits.containsKey(o))
			nonCommits.put(o, ref.getName());
	}

	private int minCommitTime() throws IOException {
		int min = Integer.MAX_VALUE;
		for (ObjectId id : revs) {
			RevObject o = walk.parseAny(id);
			while (o instanceof RevTag) {
				o = ((RevTag) o).getObject();
				walk.parseHeaders(o);
			}
			if (o instanceof RevCommit) {
				RevCommit c = (RevCommit) o;
				if (c.getCommitTime() < min)
					min = c.getCommitTime();
			}
		}
		return min;
	}

	private long compare(String leftTip, long leftCost, String rightTip, long rightCost) {
		long c = leftCost - rightCost;
		if (c != 0 || prefixes.isEmpty())
			return c;
		int li = -1;
		int ri = -1;
		for (int i = 0; i < prefixes.size(); i++) {
			String prefix = prefixes.get(i);
			if (li < 0 && leftTip.startsWith(prefix))
				li = i;
			if (ri < 0 && rightTip.startsWith(prefix))
				ri = i;
		}
		// Don't tiebreak if prefixes are the same, in order to prefer first-parent
		// paths.
		return li - ri;
	}

	private static String simplify(String refName) {
		if (refName.startsWith(Constants.R_HEADS))
			return refName.substring(Constants.R_HEADS.length());
		if (refName.startsWith(Constants.R_TAGS))
			return refName.substring(Constants.R_TAGS.length());
		if (refName.startsWith(Constants.R_REFS))
			return refName.substring(Constants.R_REFS.length());
		return refName;
	}
}
