/*
 * 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 org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
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.errors.InvalidPatternException;
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
	public boolean useAnnotatedTags;

	@Parameters
	public static Collection<Boolean[]> getUseAnnotatedTagsValues() {
		return Arrays.asList(new Boolean[][] { { Boolean.TRUE },
				{ Boolean.FALSE } });
	}

	@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");

		assertNull(describe(c1));
		assertNull(describe(c1, true));
		assertNull(describe(c1, "a*", "b*", "c*"));

		assertEquals("alice-t1", describe(c2));
		assertEquals("alice-t1", describe(c2, "alice*"));
		assertNull(describe(c2, "bob*"));
		assertNull(describe(c2, "?ob*"));
		assertEquals("alice-t1", describe(c2, "a*", "b*", "c*"));

		assertEquals("bob-t2", describe(c3));
		assertEquals("bob-t2-0-g44579eb", describe(c3, true));
		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*"));

		assertNameStartsWith(c4, "3e563c5");
		// the value verified with git-describe(1)
		assertEquals("bob-t2-1-g3e563c5", describe(c4));
		assertEquals("bob-t2-1-g3e563c5", describe(c4, true));
		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*"));

		// test default target
		assertEquals("bob-t2-1-g3e563c5", git.describe().call());
	}

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

		// Ensure that if we're interested in any tags, we get the first match as per Git behaviour
		assertEquals("v1.0.0", describe(c1));
		assertEquals("v1.0.0-1-g3747db3", describe(c2));

		// Ensure that if we're only interested in one of multiple tags, we get the right match
		assertEquals("v1.0.0", describe(c1, "v1.0*"));
		assertEquals("v1.1.1", describe(c1, "v1.1*"));
		assertEquals("v1.0.0-1-g3747db3", describe(c2, "v1.0*"));
		assertEquals("v1.1.1-1-g3747db3", describe(c2, "v1.1*"));

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

	/**
	 * Make sure it finds a tag when not all ancestries include a tag.
	 *
	 * <pre>
	 * c1 -+-> T  -
	 *     |       |
	 *     +-> c3 -+-> 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");
		assertEquals("t-2-g119892b", describe(c4)); // 2 commits: c4 and c3
		assertNull(describe(c3));
		assertNull(describe(c3, true));
	}

	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 -+-> t2  -
	 *     |       |
	 *     +-> c3 -+-> 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");

		ObjectId c4 = merge(c2);

		assertNameStartsWith(c4, "119892b");
		assertEquals("t2-2-g119892b", describe(c4)); // 2 commits: c4 and c3

		assertNameStartsWith(c3, "0244e7f");
		assertEquals("t1-1-g0244e7f", describe(c3));
	}

	/**
	 * When t1 is nearer than t2, t2 should be found
	 *
	 * <pre>
	 * c1 -+-> c2 -> t1 -+
	 *     |             |
	 *     +-> t2 -> c3 -+-> 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");
		assertEquals("t1-3-gbb389a4", describe(c4));
	}

	/**
	 * When t1 and t2 have same depth native git seems to add the depths of both
	 * paths
	 *
	 * <pre>
	 * c1 -+-> t1 -> c2 -+
	 *     |             |
	 *     +-> t2 -> c3 -+-> 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");
		assertEquals("t2-4-gbb389a4", describe(c4));
	}

	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 {
		TagCommand tagCommand = git.tag().setName(tag)
				.setAnnotated(useAnnotatedTags);
		if (useAnnotatedTags)
			tagCommand.setMessage(tag);
		tagCommand.call();
	}

	private static void touch(File f, String contents) throws Exception {
		FileWriter w = new FileWriter(f);
		w.write(contents);
		w.close();
	}

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

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

	private String describe(ObjectId c1, String... patterns) throws GitAPIException, IOException, InvalidPatternException {
		return git.describe().setTarget(c1).setMatch(patterns).call();
	}

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