/*
 * Copyright (c) 2020, Google LLC  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
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

package org.eclipse.jgit.merge;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.io.IOException;

import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheBuilder;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.test.resources.SampleDataRepositoryTestCase;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.junit.Test;

public class GitlinkMergeTest extends SampleDataRepositoryTestCase {
	private static final String LINK_ID1 = "DEADBEEFDEADBEEFBABEDEADBEEFDEADBEEFBABE";
	private static final String LINK_ID2 = "DEADDEADDEADDEADDEADDEADDEADDEADDEADDEAD";
	private static final String LINK_ID3 = "BEEFBEEFBEEFBEEFBEEFBEEFBEEFBEEFBEEFBEEF";

	private static final String SUBMODULE_PATH = "submodule.link";

	@Test
	public void testGitLinkMerging_AddNew() throws Exception {
		assertGitLinkValue(
				testGitLink(null, null, LINK_ID3, newResolveMerger(), true),
				LINK_ID3);
	}

	@Test
	public void testGitLinkMerging_Delete() throws Exception {
		assertGitLinkDoesntExist(testGitLink(LINK_ID1, LINK_ID1, null,
				newResolveMerger(), true));
	}

	@Test
	public void testGitLinkMerging_UpdateDelete() throws Exception {
		testGitLink(LINK_ID1, LINK_ID2, null, newResolveMerger(), false);
	}

	@Test
	public void testGitLinkMerging_DeleteUpdate() throws Exception {
		testGitLink(LINK_ID1, null, LINK_ID3, newResolveMerger(), false);
	}

	@Test
	public void testGitLinkMerging_UpdateUpdate() throws Exception {
		testGitLink(LINK_ID1, LINK_ID2, LINK_ID3, newResolveMerger(), false);
	}

	@Test
	public void testGitLinkMerging_bothAddedSameLink() throws Exception {
		assertGitLinkValue(
				testGitLink(null, LINK_ID2, LINK_ID2, newResolveMerger(), true),
				LINK_ID2);
	}

	@Test
	public void testGitLinkMerging_bothAddedDifferentLink() throws Exception {
		testGitLink(null, LINK_ID2, LINK_ID3, newResolveMerger(), false);
	}

	@Test
	public void testGitLinkMerging_AddNew_ignoreConflicts() throws Exception {
		assertGitLinkValue(
				testGitLink(null, null, LINK_ID3, newIgnoreConflictMerger(),
						true),
				LINK_ID3);
	}

	@Test
	public void testGitLinkMerging_Delete_ignoreConflicts() throws Exception {
		assertGitLinkDoesntExist(testGitLink(LINK_ID1, LINK_ID1, null,
				newIgnoreConflictMerger(), true));
	}

	@Test
	public void testGitLinkMerging_UpdateDelete_ignoreConflicts()
			throws Exception {
		assertGitLinkValue(testGitLink(LINK_ID1, LINK_ID2, null,
				newIgnoreConflictMerger(), true), LINK_ID2);
	}

	@Test
	public void testGitLinkMerging_DeleteUpdate_ignoreConflicts()
			throws Exception {
		assertGitLinkDoesntExist(testGitLink(LINK_ID1, null, LINK_ID3,
				newIgnoreConflictMerger(), true));
	}

	@Test
	public void testGitLinkMerging_UpdateUpdate_ignoreConflicts()
			throws Exception {
		assertGitLinkValue(testGitLink(LINK_ID1, LINK_ID2, LINK_ID3,
				newIgnoreConflictMerger(), true), LINK_ID2);
	}

	@Test
	public void testGitLinkMerging_bothAddedSameLink_ignoreConflicts()
			throws Exception {
		assertGitLinkValue(testGitLink(null, LINK_ID2, LINK_ID2,
				newIgnoreConflictMerger(), true), LINK_ID2);
	}

	@Test
	public void testGitLinkMerging_bothAddedDifferentLink_ignoreConflicts()
			throws Exception {
		assertGitLinkValue(testGitLink(null, LINK_ID2, LINK_ID3,
				newIgnoreConflictMerger(), true), LINK_ID2);
	}

	protected Merger testGitLink(@Nullable String baseLink,
			@Nullable String oursLink, @Nullable String theirsLink,
			Merger merger, boolean shouldMerge)
			throws Exception {
		DirCache treeB = db.readDirCache();
		DirCache treeO = db.readDirCache();
		DirCache treeT = db.readDirCache();

		DirCacheBuilder bTreeBuilder = treeB.builder();
		DirCacheBuilder oTreeBuilder = treeO.builder();
		DirCacheBuilder tTreeBuilder = treeT.builder();

		maybeAddLink(bTreeBuilder, baseLink);
		maybeAddLink(oTreeBuilder, oursLink);
		maybeAddLink(tTreeBuilder, theirsLink);

		bTreeBuilder.finish();
		oTreeBuilder.finish();
		tTreeBuilder.finish();

		ObjectInserter ow = db.newObjectInserter();
		ObjectId b = commit(ow, treeB, new ObjectId[] {});
		ObjectId o = commit(ow, treeO, new ObjectId[] { b });
		ObjectId t = commit(ow, treeT, new ObjectId[] { b });

		boolean merge = merger.merge(new ObjectId[] { o, t });
		assertEquals(Boolean.valueOf(shouldMerge), Boolean.valueOf(merge));

		return merger;
	}

	private Merger newResolveMerger() {
		return MergeStrategy.RESOLVE.newMerger(db, true);
	}

	private Merger newIgnoreConflictMerger() {
		return new ResolveMerger(db, true) {
			@Override
			protected boolean mergeImpl() throws IOException {
				// emulate call with ignore conflicts.
				return mergeTrees(mergeBase(), sourceTrees[0], sourceTrees[1],
						true);
			}
		};
	}

	@Test
	public void testGitLinkMerging_blobWithLink() throws Exception {
		DirCache treeB = db.readDirCache();
		DirCache treeO = db.readDirCache();
		DirCache treeT = db.readDirCache();

		DirCacheBuilder bTreeBuilder = treeB.builder();
		DirCacheBuilder oTreeBuilder = treeO.builder();
		DirCacheBuilder tTreeBuilder = treeT.builder();

		bTreeBuilder.add(
				createEntry(SUBMODULE_PATH, FileMode.REGULAR_FILE, "blob"));
		oTreeBuilder.add(
				createEntry(SUBMODULE_PATH, FileMode.REGULAR_FILE, "blob 2"));

		maybeAddLink(tTreeBuilder, LINK_ID3);

		bTreeBuilder.finish();
		oTreeBuilder.finish();
		tTreeBuilder.finish();

		ObjectInserter ow = db.newObjectInserter();
		ObjectId b = commit(ow, treeB, new ObjectId[] {});
		ObjectId o = commit(ow, treeO, new ObjectId[] { b });
		ObjectId t = commit(ow, treeT, new ObjectId[] { b });

		Merger resolveMerger = MergeStrategy.RESOLVE.newMerger(db);
		boolean merge = resolveMerger.merge(new ObjectId[] { o, t });
		assertFalse(merge);
	}

	@Test
	public void testGitLinkMerging_linkWithBlob() throws Exception {
		DirCache treeB = db.readDirCache();
		DirCache treeO = db.readDirCache();
		DirCache treeT = db.readDirCache();

		DirCacheBuilder bTreeBuilder = treeB.builder();
		DirCacheBuilder oTreeBuilder = treeO.builder();
		DirCacheBuilder tTreeBuilder = treeT.builder();

		maybeAddLink(bTreeBuilder, LINK_ID1);
		maybeAddLink(oTreeBuilder, LINK_ID2);
		tTreeBuilder.add(
				createEntry(SUBMODULE_PATH, FileMode.REGULAR_FILE, "blob 3"));

		bTreeBuilder.finish();
		oTreeBuilder.finish();
		tTreeBuilder.finish();

		ObjectInserter ow = db.newObjectInserter();
		ObjectId b = commit(ow, treeB, new ObjectId[] {});
		ObjectId o = commit(ow, treeO, new ObjectId[] { b });
		ObjectId t = commit(ow, treeT, new ObjectId[] { b });

		Merger resolveMerger = MergeStrategy.RESOLVE.newMerger(db);
		boolean merge = resolveMerger.merge(new ObjectId[] { o, t });
		assertFalse(merge);
	}

	@Test
	public void testGitLinkMerging_linkWithLink() throws Exception {
		DirCache treeB = db.readDirCache();
		DirCache treeO = db.readDirCache();
		DirCache treeT = db.readDirCache();

		DirCacheBuilder bTreeBuilder = treeB.builder();
		DirCacheBuilder oTreeBuilder = treeO.builder();
		DirCacheBuilder tTreeBuilder = treeT.builder();

		bTreeBuilder.add(
				createEntry(SUBMODULE_PATH, FileMode.REGULAR_FILE, "blob"));
		maybeAddLink(oTreeBuilder, LINK_ID2);
		maybeAddLink(tTreeBuilder, LINK_ID3);

		bTreeBuilder.finish();
		oTreeBuilder.finish();
		tTreeBuilder.finish();

		ObjectInserter ow = db.newObjectInserter();
		ObjectId b = commit(ow, treeB, new ObjectId[] {});
		ObjectId o = commit(ow, treeO, new ObjectId[] { b });
		ObjectId t = commit(ow, treeT, new ObjectId[] { b });

		Merger resolveMerger = MergeStrategy.RESOLVE.newMerger(db);
		boolean merge = resolveMerger.merge(new ObjectId[] { o, t });
		assertFalse(merge);
	}

	@Test
	public void testGitLinkMerging_blobWithBlobFromLink() throws Exception {
		DirCache treeB = db.readDirCache();
		DirCache treeO = db.readDirCache();
		DirCache treeT = db.readDirCache();

		DirCacheBuilder bTreeBuilder = treeB.builder();
		DirCacheBuilder oTreeBuilder = treeO.builder();
		DirCacheBuilder tTreeBuilder = treeT.builder();

		maybeAddLink(bTreeBuilder, LINK_ID1);
		oTreeBuilder.add(
				createEntry(SUBMODULE_PATH, FileMode.REGULAR_FILE, "blob 2"));
		tTreeBuilder.add(
				createEntry(SUBMODULE_PATH, FileMode.REGULAR_FILE, "blob 3"));

		bTreeBuilder.finish();
		oTreeBuilder.finish();
		tTreeBuilder.finish();

		ObjectInserter ow = db.newObjectInserter();
		ObjectId b = commit(ow, treeB, new ObjectId[] {});
		ObjectId o = commit(ow, treeO, new ObjectId[] { b });
		ObjectId t = commit(ow, treeT, new ObjectId[] { b });

		Merger resolveMerger = MergeStrategy.RESOLVE.newMerger(db);
		boolean merge = resolveMerger.merge(new ObjectId[] { o, t });
		assertFalse(merge);
	}

	@Test
	public void testGitLinkMerging_linkBlobDeleted() throws Exception {
		// We changed a link to a blob, others has deleted this link.
		DirCache treeB = db.readDirCache();
		DirCache treeO = db.readDirCache();
		DirCache treeT = db.readDirCache();

		DirCacheBuilder bTreeBuilder = treeB.builder();
		DirCacheBuilder oTreeBuilder = treeO.builder();
		DirCacheBuilder tTreeBuilder = treeT.builder();

		maybeAddLink(bTreeBuilder, LINK_ID1);
		oTreeBuilder.add(
				createEntry(SUBMODULE_PATH, FileMode.REGULAR_FILE, "blob 2"));

		bTreeBuilder.finish();
		oTreeBuilder.finish();
		tTreeBuilder.finish();

		ObjectInserter ow = db.newObjectInserter();
		ObjectId b = commit(ow, treeB, new ObjectId[] {});
		ObjectId o = commit(ow, treeO, new ObjectId[] { b });
		ObjectId t = commit(ow, treeT, new ObjectId[] { b });

		Merger resolveMerger = MergeStrategy.RESOLVE.newMerger(db);
		boolean merge = resolveMerger.merge(new ObjectId[] { o, t });
		assertFalse(merge);
	}

	private void maybeAddLink(DirCacheBuilder builder,
			@Nullable String linkId) {
		if (linkId == null) {
			return;
		}
		DirCacheEntry newLink = createGitLink(SUBMODULE_PATH,
				ObjectId.fromString(linkId));
		builder.add(newLink);
	}

	private void assertGitLinkValue(Merger resolveMerger, String expectedValue)
			throws Exception {
		try (TreeWalk tw = new TreeWalk(db)) {
			tw.setRecursive(true);
			tw.reset(resolveMerger.getResultTreeId());

			assertTrue(tw.next());
			assertEquals(SUBMODULE_PATH, tw.getPathString());
			assertEquals(ObjectId.fromString(expectedValue), tw.getObjectId(0));

			assertFalse(tw.next());
		}
	}

	private void assertGitLinkDoesntExist(Merger resolveMerger)
			throws Exception {
		try (TreeWalk tw = new TreeWalk(db)) {
			tw.setRecursive(true);
			tw.reset(resolveMerger.getResultTreeId());

			assertFalse(tw.next());
		}
	}

	private static ObjectId commit(ObjectInserter odi, DirCache treeB,
			ObjectId[] parentIds) throws Exception {
		CommitBuilder c = new CommitBuilder();
		c.setTreeId(treeB.writeTree(odi));
		c.setAuthor(new PersonIdent("A U Thor", "a.u.thor", 1L, 0));
		c.setCommitter(c.getAuthor());
		c.setParentIds(parentIds);
		c.setMessage("Tree " + c.getTreeId().name());
		ObjectId id = odi.insert(c);
		odi.flush();
		return id;
	}
}
