/*
 * Copyright (C) 2010, Google 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.notes;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.util.Iterator;

import org.eclipse.jgit.junit.RepositoryTestCase;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.MutableObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevBlob;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.util.RawParseUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class NoteMapTest extends RepositoryTestCase {
	private TestRepository<Repository> tr;

	private ObjectReader reader;

	private ObjectInserter inserter;

	@Override
	@Before
	public void setUp() throws Exception {
		super.setUp();

		tr = new TestRepository<>(db);
		reader = db.newObjectReader();
		inserter = db.newObjectInserter();
	}

	@Override
	@After
	public void tearDown() throws Exception {
		reader.close();
		inserter.close();
		super.tearDown();
	}

	@Test
	public void testReadFlatTwoNotes() throws Exception {
		RevBlob a = tr.blob("a");
		RevBlob b = tr.blob("b");
		RevBlob data1 = tr.blob("data1");
		RevBlob data2 = tr.blob("data2");

		RevCommit r = tr.commit() //
				.add(a.name(), data1) //
				.add(b.name(), data2) //
				.create();
		tr.parseBody(r);

		NoteMap map = NoteMap.read(reader, r);
		assertNotNull("have map", map);

		assertTrue("has note for a", map.contains(a));
		assertTrue("has note for b", map.contains(b));
		assertEquals(data1, map.get(a));
		assertEquals(data2, map.get(b));

		assertFalse("no note for data1", map.contains(data1));
		assertNull("no note for data1", map.get(data1));
	}

	@Test
	public void testReadFanout2_38() throws Exception {
		RevBlob a = tr.blob("a");
		RevBlob b = tr.blob("b");
		RevBlob data1 = tr.blob("data1");
		RevBlob data2 = tr.blob("data2");

		RevCommit r = tr.commit() //
				.add(fanout(2, a.name()), data1) //
				.add(fanout(2, b.name()), data2) //
				.create();
		tr.parseBody(r);

		NoteMap map = NoteMap.read(reader, r);
		assertNotNull("have map", map);

		assertTrue("has note for a", map.contains(a));
		assertTrue("has note for b", map.contains(b));
		assertEquals(data1, map.get(a));
		assertEquals(data2, map.get(b));

		assertFalse("no note for data1", map.contains(data1));
		assertNull("no note for data1", map.get(data1));
	}

	@Test
	public void testReadFanout2_2_36() throws Exception {
		RevBlob a = tr.blob("a");
		RevBlob b = tr.blob("b");
		RevBlob data1 = tr.blob("data1");
		RevBlob data2 = tr.blob("data2");

		RevCommit r = tr.commit() //
				.add(fanout(4, a.name()), data1) //
				.add(fanout(4, b.name()), data2) //
				.create();
		tr.parseBody(r);

		NoteMap map = NoteMap.read(reader, r);
		assertNotNull("have map", map);

		assertTrue("has note for a", map.contains(a));
		assertTrue("has note for b", map.contains(b));
		assertEquals(data1, map.get(a));
		assertEquals(data2, map.get(b));

		assertFalse("no note for data1", map.contains(data1));
		assertNull("no note for data1", map.get(data1));
	}

	@Test
	public void testReadFullyFannedOut() throws Exception {
		RevBlob a = tr.blob("a");
		RevBlob b = tr.blob("b");
		RevBlob data1 = tr.blob("data1");
		RevBlob data2 = tr.blob("data2");

		RevCommit r = tr.commit() //
				.add(fanout(38, a.name()), data1) //
				.add(fanout(38, b.name()), data2) //
				.create();
		tr.parseBody(r);

		NoteMap map = NoteMap.read(reader, r);
		assertNotNull("have map", map);

		assertTrue("has note for a", map.contains(a));
		assertTrue("has note for b", map.contains(b));
		assertEquals(data1, map.get(a));
		assertEquals(data2, map.get(b));

		assertFalse("no note for data1", map.contains(data1));
		assertNull("no note for data1", map.get(data1));
	}

	@Test
	public void testGetCachedBytes() throws Exception {
		final String exp = "this is test data";
		RevBlob a = tr.blob("a");
		RevBlob data = tr.blob(exp);

		RevCommit r = tr.commit() //
				.add(a.name(), data) //
				.create();
		tr.parseBody(r);

		NoteMap map = NoteMap.read(reader, r);
		byte[] act = map.getCachedBytes(a, exp.length() * 4);
		assertNotNull("has data for a", act);
		assertEquals(exp, RawParseUtils.decode(act));
	}

	@Test
	public void testWriteUnchangedFlat() throws Exception {
		RevBlob a = tr.blob("a");
		RevBlob b = tr.blob("b");
		RevBlob data1 = tr.blob("data1");
		RevBlob data2 = tr.blob("data2");

		RevCommit r = tr.commit() //
				.add(a.name(), data1) //
				.add(b.name(), data2) //
				.add(".gitignore", "") //
				.add("zoo-animals.txt", "") //
				.create();
		tr.parseBody(r);

		NoteMap map = NoteMap.read(reader, r);
		assertTrue("has note for a", map.contains(a));
		assertTrue("has note for b", map.contains(b));

		RevCommit n = commitNoteMap(map);
		assertNotSame("is new commit", r, n);
		assertSame("same tree", r.getTree(), n.getTree());
	}

	@Test
	public void testWriteUnchangedFanout2_38() throws Exception {
		RevBlob a = tr.blob("a");
		RevBlob b = tr.blob("b");
		RevBlob data1 = tr.blob("data1");
		RevBlob data2 = tr.blob("data2");

		RevCommit r = tr.commit() //
				.add(fanout(2, a.name()), data1) //
				.add(fanout(2, b.name()), data2) //
				.add(".gitignore", "") //
				.add("zoo-animals.txt", "") //
				.create();
		tr.parseBody(r);

		NoteMap map = NoteMap.read(reader, r);
		assertTrue("has note for a", map.contains(a));
		assertTrue("has note for b", map.contains(b));

		// This is a non-lazy map, so we'll be looking at the leaf buckets.
		RevCommit n = commitNoteMap(map);
		assertNotSame("is new commit", r, n);
		assertSame("same tree", r.getTree(), n.getTree());

		// Use a lazy-map for the next round of the same test.
		map = NoteMap.read(reader, r);
		n = commitNoteMap(map);
		assertNotSame("is new commit", r, n);
		assertSame("same tree", r.getTree(), n.getTree());
	}

	@Test
	public void testCreateFromEmpty() throws Exception {
		RevBlob a = tr.blob("a");
		RevBlob b = tr.blob("b");
		RevBlob data1 = tr.blob("data1");
		RevBlob data2 = tr.blob("data2");

		NoteMap map = NoteMap.newEmptyMap();
		assertFalse("no a", map.contains(a));
		assertFalse("no b", map.contains(b));

		map.set(a, data1);
		map.set(b, data2);

		assertEquals(data1, map.get(a));
		assertEquals(data2, map.get(b));

		map.remove(a);
		map.remove(b);

		assertFalse("no a", map.contains(a));
		assertFalse("no b", map.contains(b));

		map.set(a, "data1", inserter);
		assertEquals(data1, map.get(a));

		map.set(a, null, inserter);
		assertFalse("no a", map.contains(a));
	}

	@Test
	public void testEditFlat() throws Exception {
		RevBlob a = tr.blob("a");
		RevBlob b = tr.blob("b");
		RevBlob data1 = tr.blob("data1");
		RevBlob data2 = tr.blob("data2");

		RevCommit r = tr.commit() //
				.add(a.name(), data1) //
				.add(b.name(), data2) //
				.add(".gitignore", "") //
				.add("zoo-animals.txt", b) //
				.create();
		tr.parseBody(r);

		NoteMap map = NoteMap.read(reader, r);
		map.set(a, data2);
		map.set(b, null);
		map.set(data1, b);
		map.set(data2, null);

		assertEquals(data2, map.get(a));
		assertEquals(b, map.get(data1));
		assertFalse("no b", map.contains(b));
		assertFalse("no data2", map.contains(data2));

		MutableObjectId id = new MutableObjectId();
		for (int p = 42; p > 0; p--) {
			id.setByte(1, p);
			map.set(id, data1);
		}

		for (int p = 42; p > 0; p--) {
			id.setByte(1, p);
			assertTrue("contains " + id, map.contains(id));
		}

		RevCommit n = commitNoteMap(map);
		map = NoteMap.read(reader, n);
		assertEquals(data2, map.get(a));
		assertEquals(b, map.get(data1));
		assertFalse("no b", map.contains(b));
		assertFalse("no data2", map.contains(data2));
		assertEquals(b, TreeWalk
				.forPath(reader, "zoo-animals.txt", n.getTree()).getObjectId(0));
	}

	@Test
	public void testEditFanout2_38() throws Exception {
		RevBlob a = tr.blob("a");
		RevBlob b = tr.blob("b");
		RevBlob data1 = tr.blob("data1");
		RevBlob data2 = tr.blob("data2");

		RevCommit r = tr.commit() //
				.add(fanout(2, a.name()), data1) //
				.add(fanout(2, b.name()), data2) //
				.add(".gitignore", "") //
				.add("zoo-animals.txt", b) //
				.create();
		tr.parseBody(r);

		NoteMap map = NoteMap.read(reader, r);
		map.set(a, data2);
		map.set(b, null);
		map.set(data1, b);
		map.set(data2, null);

		assertEquals(data2, map.get(a));
		assertEquals(b, map.get(data1));
		assertFalse("no b", map.contains(b));
		assertFalse("no data2", map.contains(data2));
		RevCommit n = commitNoteMap(map);

		map.set(a, null);
		map.set(data1, null);
		assertFalse("no a", map.contains(a));
		assertFalse("no data1", map.contains(data1));

		map = NoteMap.read(reader, n);
		assertEquals(data2, map.get(a));
		assertEquals(b, map.get(data1));
		assertFalse("no b", map.contains(b));
		assertFalse("no data2", map.contains(data2));
		assertEquals(b, TreeWalk
				.forPath(reader, "zoo-animals.txt", n.getTree()).getObjectId(0));
	}

	@Test
	public void testLeafSplitsWhenFull() throws Exception {
		RevBlob data1 = tr.blob("data1");
		MutableObjectId idBuf = new MutableObjectId();

		RevCommit r = tr.commit() //
				.add(data1.name(), data1) //
				.create();
		tr.parseBody(r);

		NoteMap map = NoteMap.read(reader, r);
		for (int i = 0; i < 254; i++) {
			idBuf.setByte(Constants.OBJECT_ID_LENGTH - 1, i);
			map.set(idBuf, data1);
		}

		RevCommit n = commitNoteMap(map);
		try (TreeWalk tw = new TreeWalk(reader)) {
			tw.reset(n.getTree());
			while (tw.next()) {
				assertFalse("no fan-out subtree", tw.isSubtree());
			}
		}

		for (int i = 254; i < 256; i++) {
			idBuf.setByte(Constants.OBJECT_ID_LENGTH - 1, i);
			map.set(idBuf, data1);
		}
		idBuf.setByte(Constants.OBJECT_ID_LENGTH - 2, 1);
		map.set(idBuf, data1);
		n = commitNoteMap(map);

		// The 00 bucket is fully split.
		String path = fanout(38, idBuf.name());
		try (TreeWalk tw = TreeWalk.forPath(reader, path, n.getTree())) {
			assertNotNull("has " + path, tw);
		}

		// The other bucket is not.
		path = fanout(2, data1.name());
		try (TreeWalk tw = TreeWalk.forPath(reader, path, n.getTree())) {
			assertNotNull("has " + path, tw);
		}
	}

	@Test
	public void testRemoveDeletesTreeFanout2_38() throws Exception {
		RevBlob a = tr.blob("a");
		RevBlob data1 = tr.blob("data1");
		RevTree empty = tr.tree();

		RevCommit r = tr.commit() //
				.add(fanout(2, a.name()), data1) //
				.create();
		tr.parseBody(r);

		NoteMap map = NoteMap.read(reader, r);
		map.set(a, null);

		RevCommit n = commitNoteMap(map);
		assertEquals("empty tree", empty, n.getTree());
	}

	@Test
	public void testIteratorEmptyMap() {
		Iterator<Note> it = NoteMap.newEmptyMap().iterator();
		assertFalse(it.hasNext());
	}

	@Test
	public void testIteratorFlatTree() throws Exception {
		RevBlob a = tr.blob("a");
		RevBlob b = tr.blob("b");
		RevBlob data1 = tr.blob("data1");
		RevBlob data2 = tr.blob("data2");
		RevBlob nonNote = tr.blob("non note");

		RevCommit r = tr.commit() //
				.add(a.name(), data1) //
				.add(b.name(), data2) //
				.add("nonNote", nonNote) //
				.create();
		tr.parseBody(r);

		Iterator it = NoteMap.read(reader, r).iterator();
		assertEquals(2, count(it));
	}

	@Test
	public void testIteratorFanoutTree2_38() throws Exception {
		RevBlob a = tr.blob("a");
		RevBlob b = tr.blob("b");
		RevBlob data1 = tr.blob("data1");
		RevBlob data2 = tr.blob("data2");
		RevBlob nonNote = tr.blob("non note");

		RevCommit r = tr.commit() //
				.add(fanout(2, a.name()), data1) //
				.add(fanout(2, b.name()), data2) //
				.add("nonNote", nonNote) //
				.create();
		tr.parseBody(r);

		Iterator it = NoteMap.read(reader, r).iterator();
		assertEquals(2, count(it));
	}

	@Test
	public void testIteratorFanoutTree2_2_36() throws Exception {
		RevBlob a = tr.blob("a");
		RevBlob b = tr.blob("b");
		RevBlob data1 = tr.blob("data1");
		RevBlob data2 = tr.blob("data2");
		RevBlob nonNote = tr.blob("non note");

		RevCommit r = tr.commit() //
				.add(fanout(4, a.name()), data1) //
				.add(fanout(4, b.name()), data2) //
				.add("nonNote", nonNote) //
				.create();
		tr.parseBody(r);

		Iterator it = NoteMap.read(reader, r).iterator();
		assertEquals(2, count(it));
	}

	@Test
	public void testIteratorFullyFannedOut() throws Exception {
		RevBlob a = tr.blob("a");
		RevBlob b = tr.blob("b");
		RevBlob data1 = tr.blob("data1");
		RevBlob data2 = tr.blob("data2");
		RevBlob nonNote = tr.blob("non note");

		RevCommit r = tr.commit() //
				.add(fanout(38, a.name()), data1) //
				.add(fanout(38, b.name()), data2) //
				.add("nonNote", nonNote) //
				.create();
		tr.parseBody(r);

		Iterator it = NoteMap.read(reader, r).iterator();
		assertEquals(2, count(it));
	}

	@Test
	public void testShorteningNoteRefName() throws Exception {
		String expectedShortName = "review";
		String noteRefName = Constants.R_NOTES + expectedShortName;
		assertEquals(expectedShortName, NoteMap.shortenRefName(noteRefName));
		String nonNoteRefName = Constants.R_HEADS + expectedShortName;
		assertEquals(nonNoteRefName, NoteMap.shortenRefName(nonNoteRefName));
	}

	private RevCommit commitNoteMap(NoteMap map) throws IOException {
		tr.tick(600);

		CommitBuilder builder = new CommitBuilder();
		builder.setTreeId(map.writeTree(inserter));
		tr.setAuthorAndCommitter(builder);
		return tr.getRevWalk().parseCommit(inserter.insert(builder));
	}

	private static String fanout(int prefix, String name) {
		StringBuilder r = new StringBuilder();
		int i = 0;
		for (; i < prefix && i < name.length(); i += 2) {
			if (i != 0)
				r.append('/');
			r.append(name.charAt(i + 0));
			r.append(name.charAt(i + 1));
		}
		if (i < name.length()) {
			if (i != 0)
				r.append('/');
			r.append(name.substring(i));
		}
		return r.toString();
	}

	private static int count(Iterator it) {
		int c = 0;
		while (it.hasNext()) {
			c++;
			it.next();
		}
		return c;
	}
}
