/*
 * Copyright (C) 2017, Google 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.internal.storage.reftable;

import static org.eclipse.jgit.lib.Constants.OBJECT_ID_LENGTH;
import static org.eclipse.jgit.lib.Ref.Storage.NEW;
import static org.eclipse.jgit.lib.Ref.Storage.PACKED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;

import org.eclipse.jgit.internal.storage.io.BlockSource;
import org.eclipse.jgit.internal.storage.reftable.ReftableWriter.Stats;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef;
import org.eclipse.jgit.lib.Ref;
import org.junit.Test;

public class ReftableCompactorTest {
	private static final String MASTER = "refs/heads/master";
	private static final String NEXT = "refs/heads/next";

	@Test
	public void noTables() throws IOException {
		ReftableCompactor compactor;
		try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
			compactor = new ReftableCompactor(out);
			compactor.compact();
		}
		Stats stats = compactor.getStats();
		assertEquals(0, stats.minUpdateIndex());
		assertEquals(0, stats.maxUpdateIndex());
		assertEquals(0, stats.refCount());
	}

	@Test
	public void oneTable() throws IOException {
		byte[] inTab;
		try (ByteArrayOutputStream inBuf = new ByteArrayOutputStream()) {
			ReftableWriter writer = new ReftableWriter(inBuf)
				.setMinUpdateIndex(0)
				.setMaxUpdateIndex(0)
				.begin();

			writer.writeRef(ref(MASTER, 1));
			writer.finish();
			inTab = inBuf.toByteArray();
		}

		byte[] outTab;
		ReftableCompactor compactor;
		try (ByteArrayOutputStream outBuf = new ByteArrayOutputStream()) {
			compactor = new ReftableCompactor(outBuf);
			compactor.tryAddFirst(read(inTab));
			compactor.compact();
			outTab = outBuf.toByteArray();
		}
		Stats stats = compactor.getStats();
		assertEquals(0, stats.minUpdateIndex());
		assertEquals(0, stats.maxUpdateIndex());
		assertEquals(1, stats.refCount());

		ReftableReader rr = read(outTab);
		try (RefCursor rc = rr.allRefs()) {
			assertTrue(rc.next());
			assertEquals(MASTER, rc.getRef().getName());
			assertEquals(id(1), rc.getRef().getObjectId());
			assertEquals(0, rc.getRef().getUpdateIndex());
		}
	}

	@Test
	public void twoTablesOneRef() throws IOException {
		byte[] inTab1;
		try (ByteArrayOutputStream inBuf = new ByteArrayOutputStream()) {
			ReftableWriter writer = new ReftableWriter(inBuf)
				.setMinUpdateIndex(0)
				.setMaxUpdateIndex(0)
				.begin();

			writer.writeRef(ref(MASTER, 1));
			writer.finish();
			inTab1 = inBuf.toByteArray();
		}

		byte[] inTab2;
		try (ByteArrayOutputStream inBuf = new ByteArrayOutputStream()) {
			ReftableWriter writer = new ReftableWriter(inBuf)
				.setMinUpdateIndex(1)
				.setMaxUpdateIndex(1)
				.begin();

			writer.writeRef(ref(MASTER, 2));
			writer.finish();
			inTab2 = inBuf.toByteArray();
		}

		byte[] outTab;
		ReftableCompactor compactor;
		try (ByteArrayOutputStream outBuf = new ByteArrayOutputStream()) {
			compactor = new ReftableCompactor(outBuf);
			compactor.addAll(Arrays.asList(read(inTab1), read(inTab2)));
			compactor.compact();
			outTab = outBuf.toByteArray();
		}
		Stats stats = compactor.getStats();
		assertEquals(0, stats.minUpdateIndex());
		assertEquals(1, stats.maxUpdateIndex());
		assertEquals(1, stats.refCount());

		ReftableReader rr = read(outTab);
		try (RefCursor rc = rr.allRefs()) {
			assertTrue(rc.next());
			assertEquals(MASTER, rc.getRef().getName());
			assertEquals(id(2), rc.getRef().getObjectId());
			assertEquals(1, rc.getRef().getUpdateIndex());
		}
	}

	@Test
	public void twoTablesTwoRefs() throws IOException {
		byte[] inTab1;
		try (ByteArrayOutputStream inBuf = new ByteArrayOutputStream()) {
			ReftableWriter writer = new ReftableWriter(inBuf)
				.setMinUpdateIndex(0)
				.setMaxUpdateIndex(0)
				.begin();

			writer.writeRef(ref(MASTER, 1));
			writer.writeRef(ref(NEXT, 2));
			writer.finish();
			inTab1 = inBuf.toByteArray();
		}

		byte[] inTab2;
		try (ByteArrayOutputStream inBuf = new ByteArrayOutputStream()) {
			ReftableWriter writer = new ReftableWriter(inBuf)
				.setMinUpdateIndex(1)
				.setMaxUpdateIndex(1)
				.begin();

			writer.writeRef(ref(MASTER, 3));
			writer.finish();
			inTab2 = inBuf.toByteArray();
		}

		byte[] outTab;
		ReftableCompactor compactor;
		try (ByteArrayOutputStream outBuf = new ByteArrayOutputStream()) {
			compactor =  new ReftableCompactor(outBuf);
			compactor.addAll(Arrays.asList(read(inTab1), read(inTab2)));
			compactor.compact();
			outTab = outBuf.toByteArray();
		}
		Stats stats = compactor.getStats();
		assertEquals(0, stats.minUpdateIndex());
		assertEquals(1, stats.maxUpdateIndex());
		assertEquals(2, stats.refCount());

		ReftableReader rr = read(outTab);
		try (RefCursor rc = rr.allRefs()) {
			assertTrue(rc.next());
			assertEquals(MASTER, rc.getRef().getName());
			assertEquals(id(3), rc.getRef().getObjectId());
			assertEquals(1, rc.getRef().getUpdateIndex());

			assertTrue(rc.next());
			assertEquals(NEXT, rc.getRef().getName());
			assertEquals(id(2), rc.getRef().getObjectId());
			assertEquals(0, rc.getRef().getUpdateIndex());
		}
	}

	@Test
	public void twoTablesIncludeOneDelete() throws IOException {
		byte[] inTab1;
		try (ByteArrayOutputStream inBuf = new ByteArrayOutputStream()) {
			ReftableWriter writer = new ReftableWriter(inBuf)
				.setMinUpdateIndex(0)
				.setMaxUpdateIndex(0)
				.begin();

			writer.writeRef(ref(MASTER, 1));
			writer.finish();
			inTab1 = inBuf.toByteArray();
		}

		byte[] inTab2;
		try (ByteArrayOutputStream inBuf = new ByteArrayOutputStream()) {
			ReftableWriter writer = new ReftableWriter(inBuf)
				.setMinUpdateIndex(1)
				.setMaxUpdateIndex(1)
				.begin();

			writer.writeRef(tombstone(MASTER));
			writer.finish();
			inTab2 = inBuf.toByteArray();
		}

		byte[] outTab;
		ReftableCompactor compactor;
		try (ByteArrayOutputStream outBuf = new ByteArrayOutputStream()) {
			compactor = new ReftableCompactor(outBuf);
			compactor.setIncludeDeletes(true);
			compactor.addAll(Arrays.asList(read(inTab1), read(inTab2)));
			compactor.compact();
			outTab = outBuf.toByteArray();
		}
		Stats stats = compactor.getStats();
		assertEquals(0, stats.minUpdateIndex());
		assertEquals(1, stats.maxUpdateIndex());
		assertEquals(1, stats.refCount());

		ReftableReader rr = read(outTab);
		try (RefCursor rc = rr.allRefs()) {
			assertFalse(rc.next());
		}
	}

	@Test
	public void twoTablesNotIncludeOneDelete() throws IOException {
		byte[] inTab1;
		try (ByteArrayOutputStream inBuf = new ByteArrayOutputStream()) {
			ReftableWriter writer = new ReftableWriter(inBuf)
				.setMinUpdateIndex(0)
				.setMaxUpdateIndex(0)
				.begin();

			writer.writeRef(ref(MASTER, 1));
			writer.finish();
			inTab1 = inBuf.toByteArray();
		}

		byte[] inTab2;
		try (ByteArrayOutputStream inBuf = new ByteArrayOutputStream()) {
			ReftableWriter writer = new ReftableWriter(inBuf)
				.setMinUpdateIndex(1)
				.setMaxUpdateIndex(1)
				.begin();

			writer.writeRef(tombstone(MASTER));
			writer.finish();
			inTab2 = inBuf.toByteArray();
		}

		byte[] outTab;
		ReftableCompactor compactor;
		try (ByteArrayOutputStream outBuf = new ByteArrayOutputStream()) {
			compactor = new ReftableCompactor(outBuf);
			compactor.setIncludeDeletes(false);
			compactor.addAll(Arrays.asList(read(inTab1), read(inTab2)));
			compactor.compact();
			outTab = outBuf.toByteArray();
		}
		Stats stats = compactor.getStats();
		assertEquals(0, stats.minUpdateIndex());
		assertEquals(1, stats.maxUpdateIndex());
		assertEquals(0, stats.refCount());

		ReftableReader rr = read(outTab);
		try (RefCursor rc = rr.allRefs()) {
			assertFalse(rc.next());
		}
	}

	private static Ref ref(String name, int id) {
		return new ObjectIdRef.PeeledNonTag(PACKED, name, id(id));
	}

	private static Ref tombstone(String name) {
		return new ObjectIdRef.Unpeeled(NEW, name, null);
	}

	private static ObjectId id(int i) {
		byte[] buf = new byte[OBJECT_ID_LENGTH];
		buf[0] = (byte) (i & 0xff);
		buf[1] = (byte) ((i >>> 8) & 0xff);
		buf[2] = (byte) ((i >>> 16) & 0xff);
		buf[3] = (byte) (i >>> 24);
		return ObjectId.fromRaw(buf);
	}

	private static ReftableReader read(byte[] table) {
		return new ReftableReader(BlockSource.from(table));
	}
}
