/*
 * Copyright (C) 2013, CloudBees, 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 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));
	}
}
