/*
 * Copyright (C) 2013, CloudBees, Inc. and others
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0 which is available at
 * https://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */
package org.eclipse.jgit.api;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.Collection;

import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.RefNotFoundException;
import org.eclipse.jgit.junit.RepositoryTestCase;
import org.eclipse.jgit.lib.ObjectId;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class DescribeCommandTest extends RepositoryTestCase {

	private Git git;

	@Parameter(0)
	public boolean useAnnotatedTags;

	@Parameter(1)
	public boolean describeUseAllTags;

	@Parameters(name = "git tag -a {0}?-a: with git describe {1}?--tags:")
	public static Collection<Boolean[]> getUseAnnotatedTagsValues() {
		return Arrays.asList(new Boolean[][] { { Boolean.TRUE, Boolean.FALSE },
				{ Boolean.FALSE, Boolean.FALSE },
				{ Boolean.TRUE, Boolean.TRUE },
				{ Boolean.FALSE, Boolean.TRUE } });
	}

	@Override
	public void setUp() throws Exception {
		super.setUp();
		git = new Git(db);
	}

	@Test(expected = RefNotFoundException.class)
	public void noTargetSet() throws Exception {
		git.describe().call();
	}

	@Test
	public void testDescribe() throws Exception {
		ObjectId c1 = modify("aaa");

		ObjectId c2 = modify("bbb");
		tag("alice-t1");

		ObjectId c3 = modify("ccc");
		tag("bob-t2");

		ObjectId c4 = modify("ddd");
		assertNameStartsWith(c4, "3e563c5");

		assertNull(describe(c1));
		assertNull(describe(c1, true, false));
		assertNull(describe(c1, "a*", "b*", "c*"));
		assertNull(describe(c2, "bob*"));
		assertNull(describe(c2, "?ob*"));

		if (useAnnotatedTags || describeUseAllTags) {
			assertEquals("alice-t1", describe(c2));
			assertEquals("alice-t1", describe(c2, "alice*"));
			assertEquals("alice-t1", describe(c2, "a*", "b*", "c*"));

			assertEquals("bob-t2", describe(c3));
			assertEquals("bob-t2-0-g44579eb", describe(c3, true, false));
			assertEquals("alice-t1-1-g44579eb", describe(c3, "alice*"));
			assertEquals("alice-t1-1-g44579eb", describe(c3, "a??c?-t*"));
			assertEquals("bob-t2", describe(c3, "bob*"));
			assertEquals("bob-t2", describe(c3, "?ob*"));
			assertEquals("bob-t2", describe(c3, "a*", "b*", "c*"));

			// the value verified with git-describe(1)
			assertEquals("bob-t2-1-g3e563c5", describe(c4));
			assertEquals("bob-t2-1-g3e563c5", describe(c4, true, false));
			assertEquals("alice-t1-2-g3e563c5", describe(c4, "alice*"));
			assertEquals("bob-t2-1-g3e563c5", describe(c4, "bob*"));
			assertEquals("bob-t2-1-g3e563c5", describe(c4, "a*", "b*", "c*"));
		} else {
			assertEquals(null, describe(c2));
			assertEquals(null, describe(c3));
			assertEquals(null, describe(c4));

			assertEquals("3747db3", describe(c2, false, true));
			assertEquals("44579eb", describe(c3, false, true));
			assertEquals("3e563c5", describe(c4, false, true));
		}

		// test default target
		if (useAnnotatedTags) {
			assertEquals("bob-t2-1-g3e563c5", git.describe().call());
			assertEquals("bob-t2-1-g3e563c5",
					git.describe().setTags(false).call());
			assertEquals("bob-t2-1-g3e563c5",
					git.describe().setTags(true).call());
		} else {
			assertEquals(null, git.describe().call());
			assertEquals(null, git.describe().setTags(false).call());
			assertEquals("bob-t2-1-g3e563c5",
					git.describe().setTags(true).call());
		}
	}

	@Test
	public void testDescribeMultiMatch() throws Exception {
		ObjectId c1 = modify("aaa");
		tag("v1.0.0");
		tick();
		tag("v1.0.1");
		tick();
		tag("v1.1.0");
		tick();
		tag("v1.1.1");
		ObjectId c2 = modify("bbb");

		if (!useAnnotatedTags && !describeUseAllTags) {
			assertEquals(null, describe(c1));
			assertEquals(null, describe(c2));

			assertEquals("fd70040", describe(c1, false, true));
			assertEquals("b89dead", describe(c2, false, true));

			return;
		}

		// Ensure that if we're interested in any tags, we get the most recent tag
		// as per Git behaviour since 1.7.1.1
		if (useAnnotatedTags) {
			assertEquals("v1.1.1", describe(c1));
			assertEquals("v1.1.1-1-gb89dead", describe(c2));
			// Ensure that if we're only interested in one of multiple tags, we get the right match
			assertEquals("v1.0.1", describe(c1, "v1.0*"));
			assertEquals("v1.1.1", describe(c1, "v1.1*"));
			assertEquals("v1.0.1-1-gb89dead", describe(c2, "v1.0*"));
			assertEquals("v1.1.1-1-gb89dead", describe(c2, "v1.1*"));

			// Ensure that ordering of match precedence is preserved as per Git behaviour
			assertEquals("v1.1.1", describe(c1, "v1.0*", "v1.1*"));
			assertEquals("v1.1.1", describe(c1, "v1.1*", "v1.0*"));
			assertEquals("v1.1.1-1-gb89dead", describe(c2, "v1.0*", "v1.1*"));
			assertEquals("v1.1.1-1-gb89dead", describe(c2, "v1.1*", "v1.0*"));
		} else {
			// no timestamps so no guarantees on which tag is chosen
			assertNotNull(describe(c1));
			assertNotNull(describe(c2));

			assertNotNull(describe(c1, "v1.0*"));
			assertNotNull(describe(c1, "v1.1*"));
			assertNotNull(describe(c2, "v1.0*"));
			assertNotNull(describe(c2, "v1.1*"));

			// Ensure that ordering of match precedence is preserved as per Git behaviour
			assertNotNull(describe(c1, "v1.0*", "v1.1*"));
			assertNotNull(describe(c1, "v1.1*", "v1.0*"));
			assertNotNull(describe(c2, "v1.0*", "v1.1*"));
			assertNotNull(describe(c2, "v1.1*", "v1.0*"));
		}
	}

	/**
	 * Make sure it finds a tag when not all ancestries include a tag.
	 *
	 * <pre>
	 * c1 -+-&gt; T  -
	 *     |       |
	 *     +-&gt; c3 -+-&gt; c4
	 * </pre>
	 *
	 * @throws Exception
	 */
	@Test
	public void testDescribeBranch() throws Exception {
		ObjectId c1 = modify("aaa");

		ObjectId c2 = modify("bbb");
		tag("t");

		branch("b", c1);

		ObjectId c3 = modify("ccc");

		ObjectId c4 = merge(c2);

		assertNameStartsWith(c4, "119892b");
		if (useAnnotatedTags || describeUseAllTags) {
			assertEquals("2 commits: c4 and c3", "t-2-g119892b", describe(c4));
		} else {
			assertEquals(null, describe(c4));

			assertEquals("119892b", describe(c4, false, true));
		}
		assertNull(describe(c3));
		assertNull(describe(c3, true, false));
	}

	private void branch(String name, ObjectId base) throws GitAPIException {
		git.checkout().setCreateBranch(true).setName(name)
				.setStartPoint(base.name()).call();
	}

	/**
	 * When t2 dominates t1, it's clearly preferable to describe by using t2.
	 *
	 * <pre>
	 * t1 -+-&gt; t2  -
	 *     |       |
	 *     +-&gt; c3 -+-&gt; c4
	 * </pre>
	 *
	 * @throws Exception
	 */
	@Test
	public void t1DominatesT2() throws Exception {
		ObjectId c1 = modify("aaa");
		tag("t1");

		ObjectId c2 = modify("bbb");
		tag("t2");

		branch("b", c1);

		ObjectId c3 = modify("ccc");
		assertNameStartsWith(c3, "0244e7f");

		ObjectId c4 = merge(c2);

		assertNameStartsWith(c4, "119892b");

		if (useAnnotatedTags || describeUseAllTags) {
			assertEquals("t2-2-g119892b", describe(c4)); // 2 commits: c4 and c3
			assertEquals("t1-1-g0244e7f", describe(c3));
		} else {
			assertEquals(null, describe(c4));
			assertEquals(null, describe(c3));

			assertEquals("119892b", describe(c4, false, true));
			assertEquals("0244e7f", describe(c3, false, true));
		}
	}

	/**
	 * When t1 annotated dominates t2 lightweight tag
	 *
	 * <pre>
	 * t1 -+-> t2  -
	 *     |       |
	 *     +-> c3 -+-> c4
	 * </pre>
	 *
	 * @throws Exception
	 */
	@Test
	public void t1AnnotatedDominatesT2lightweight() throws Exception {
		ObjectId c1 = modify("aaa");
		tag("t1", useAnnotatedTags);

		ObjectId c2 = modify("bbb");
		tag("t2", false);

		assertNameStartsWith(c2, "3747db3");
		if (useAnnotatedTags && !describeUseAllTags) {
			assertEquals(
					"only annotated tag t1 expected to be used for describe",
					"t1-1-g3747db3", describe(c2)); // 1 commits: t2 overridden
													// by t1
		} else if (!useAnnotatedTags && !describeUseAllTags) {
			assertEquals("no commits to describe expected", null, describe(c2));
		} else {
			assertEquals("lightweight tag t2 expected in describe", "t2",
					describe(c2));
		}

		branch("b", c1);

		ObjectId c3 = modify("ccc");

		assertNameStartsWith(c3, "0244e7f");
		if (useAnnotatedTags || describeUseAllTags) {
			assertEquals("t1-1-g0244e7f", describe(c3));
		}

		ObjectId c4 = merge(c2);

		assertNameStartsWith(c4, "119892b");
		if (describeUseAllTags) {
			assertEquals(
					"2 commits for describe commit increment expected since lightweight tag: c4 and c3",
					"t2-2-g119892b", describe(c4)); // 2 commits: c4 and c3
		} else if (!useAnnotatedTags && !describeUseAllTags) {
			assertEquals("no matching commits expected", null, describe(c4));
		} else {
			assertEquals(
					"3 commits for describe commit increment expected since annotated tag: c4 and c3 and c2",
					"t1-3-g119892b", describe(c4)); //
		}
	}

	/**
	 * When t1 is nearer than t2, t2 should be found
	 *
	 * <pre>
	 * c1 -+-&gt; c2 -&gt; t1 -+
	 *     |             |
	 *     +-&gt; t2 -&gt; c3 -+-&gt; c4
	 * </pre>
	 *
	 * @throws Exception
	 */
	@Test
	public void t1nearerT2() throws Exception {
		ObjectId c1 = modify("aaa");
		modify("bbb");
		ObjectId t1 = modify("ccc");
		tag("t1");

		branch("b", c1);
		modify("ddd");
		tag("t2");
		modify("eee");
		ObjectId c4 = merge(t1);

		assertNameStartsWith(c4, "bb389a4");
		if (useAnnotatedTags || describeUseAllTags) {
			assertEquals("t1-3-gbb389a4", describe(c4));
		} else {
			assertEquals(null, describe(c4));

			assertEquals("bb389a4", describe(c4, false, true));
		}
	}

	/**
	 * When t1 and t2 have same depth native git seems to add the depths of both
	 * paths
	 *
	 * <pre>
	 * c1 -+-&gt; t1 -&gt; c2 -+
	 *     |             |
	 *     +-&gt; t2 -&gt; c3 -+-&gt; c4
	 * </pre>
	 *
	 * @throws Exception
	 */
	@Test
	public void t1sameDepthT2() throws Exception {
		ObjectId c1 = modify("aaa");
		modify("bbb");
		tag("t1");
		ObjectId c2 = modify("ccc");

		branch("b", c1);
		modify("ddd");
		tag("t2");
		modify("eee");
		ObjectId c4 = merge(c2);

		assertNameStartsWith(c4, "bb389a4");
		if (useAnnotatedTags || describeUseAllTags) {
			assertEquals("t2-4-gbb389a4", describe(c4));
		} else {
			assertEquals(null, describe(c4));

			assertEquals("bb389a4", describe(c4, false, true));
		}
	}

	@Test
	public void globMatchWithSlashes() throws Exception {
		ObjectId c1 = modify("aaa");
		tag("a/b/version");
		ObjectId c2 = modify("bbb");
		tag("a/b/version2");
		if (useAnnotatedTags || describeUseAllTags) {
			assertEquals("a/b/version", describe(c1, "*/version*"));
			assertEquals("a/b/version2", describe(c2, "*/version*"));
		} else {
			assertNull(describe(c1));
			assertNull(describe(c1, "*/version*"));
			assertNull(describe(c2));
			assertNull(describe(c2, "*/version*"));
		}
	}

	private ObjectId merge(ObjectId c2) throws GitAPIException {
		return git.merge().include(c2).call().getNewHead();
	}

	private ObjectId modify(String content) throws Exception {
		File a = new File(db.getWorkTree(), "a.txt");
		touch(a, content);
		return git.commit().setAll(true).setMessage(content).call().getId();
	}

	private void tag(String tag) throws GitAPIException {
		tag(tag, this.useAnnotatedTags);
	}

	private void tag(String tag, boolean annotatedTag) throws GitAPIException {
		TagCommand tagCommand = git.tag().setName(tag)
				.setAnnotated(annotatedTag);
		if (annotatedTag) {
			tagCommand.setMessage(tag);
		}
		tagCommand.call();
	}

	private static void touch(File f, String contents) throws Exception {
		try (BufferedWriter w = Files.newBufferedWriter(f.toPath(), UTF_8)) {
			w.write(contents);
		}
	}

	private String describe(ObjectId c1, boolean longDesc, boolean always)
			throws GitAPIException, IOException {
		return git.describe().setTarget(c1).setTags(describeUseAllTags)
				.setLong(longDesc).setAlways(always).call();
	}

	private String describe(ObjectId c1) throws GitAPIException, IOException {
		return describe(c1, false, false);
	}

	private String describe(ObjectId c1, String... patterns) throws Exception {
		return git.describe().setTarget(c1).setTags(describeUseAllTags)
				.setMatch(patterns).call();
	}

	private static void assertNameStartsWith(ObjectId c4, String prefix) {
		assertTrue(c4.name(), c4.name().startsWith(prefix));
	}
}
