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

import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;

import junit.framework.TestCase;

import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.SymbolicRef;

public class RefMapTest extends TestCase {
	private static final ObjectId ID_ONE = ObjectId
			.fromString("41eb0d88f833b558bddeb269b7ab77399cdf98ed");

	private static final ObjectId ID_TWO = ObjectId
			.fromString("698dd0b8d0c299f080559a1cffc7fe029479a408");

	private RefList<Ref> packed;

	private RefList<Ref> loose;

	private RefList<Ref> resolved;

	protected void setUp() throws Exception {
		super.setUp();
		packed = RefList.emptyList();
		loose = RefList.emptyList();
		resolved = RefList.emptyList();
	}

	public void testEmpty_NoPrefix1() {
		RefMap map = new RefMap("", packed, loose, resolved);
		assertTrue(map.isEmpty()); // before size was computed
		assertEquals(0, map.size());
		assertTrue(map.isEmpty()); // after size was computed

		assertFalse(map.entrySet().iterator().hasNext());
		assertFalse(map.keySet().iterator().hasNext());
		assertFalse(map.containsKey("a"));
		assertNull(map.get("a"));
	}

	public void testEmpty_NoPrefix2() {
		RefMap map = new RefMap();
		assertTrue(map.isEmpty()); // before size was computed
		assertEquals(0, map.size());
		assertTrue(map.isEmpty()); // after size was computed

		assertFalse(map.entrySet().iterator().hasNext());
		assertFalse(map.keySet().iterator().hasNext());
		assertFalse(map.containsKey("a"));
		assertNull(map.get("a"));
	}

	public void testNotEmpty_NoPrefix() {
		final Ref master = newRef("refs/heads/master", ID_ONE);
		packed = toList(master);

		RefMap map = new RefMap("", packed, loose, resolved);
		assertFalse(map.isEmpty()); // before size was computed
		assertEquals(1, map.size());
		assertFalse(map.isEmpty()); // after size was computed
		assertSame(master, map.values().iterator().next());
	}

	public void testEmpty_WithPrefix() {
		final Ref master = newRef("refs/heads/master", ID_ONE);
		packed = toList(master);

		RefMap map = new RefMap("refs/tags/", packed, loose, resolved);
		assertTrue(map.isEmpty()); // before size was computed
		assertEquals(0, map.size());
		assertTrue(map.isEmpty()); // after size was computed

		assertFalse(map.entrySet().iterator().hasNext());
		assertFalse(map.keySet().iterator().hasNext());
	}

	public void testNotEmpty_WithPrefix() {
		final Ref master = newRef("refs/heads/master", ID_ONE);
		packed = toList(master);

		RefMap map = new RefMap("refs/heads/", packed, loose, resolved);
		assertFalse(map.isEmpty()); // before size was computed
		assertEquals(1, map.size());
		assertFalse(map.isEmpty()); // after size was computed
		assertSame(master, map.values().iterator().next());
	}

	public void testClear() {
		final Ref master = newRef("refs/heads/master", ID_ONE);
		loose = toList(master);

		RefMap map = new RefMap("", packed, loose, resolved);
		assertSame(master, map.get("refs/heads/master"));

		map.clear();
		assertNull(map.get("refs/heads/master"));
		assertTrue(map.isEmpty());
		assertEquals(0, map.size());
	}

	public void testIterator_RefusesRemove() {
		final Ref master = newRef("refs/heads/master", ID_ONE);
		loose = toList(master);

		RefMap map = new RefMap("", packed, loose, resolved);
		Iterator<Ref> itr = map.values().iterator();
		assertTrue(itr.hasNext());
		assertSame(master, itr.next());
		try {
			itr.remove();
			fail("iterator allowed remove");
		} catch (UnsupportedOperationException err) {
			// expected
		}
	}

	public void testIterator_FailsAtEnd() {
		final Ref master = newRef("refs/heads/master", ID_ONE);
		loose = toList(master);

		RefMap map = new RefMap("", packed, loose, resolved);
		Iterator<Ref> itr = map.values().iterator();
		assertTrue(itr.hasNext());
		assertSame(master, itr.next());
		try {
			itr.next();
			fail("iterator allowed next");
		} catch (NoSuchElementException err) {
			// expected
		}
	}

	public void testIterator_MissingUnresolvedSymbolicRefIsBug() {
		final Ref master = newRef("refs/heads/master", ID_ONE);
		final Ref headR = newRef("HEAD", master);

		loose = toList(master);
		// loose should have added newRef("HEAD", "refs/heads/master")
		resolved = toList(headR);

		RefMap map = new RefMap("", packed, loose, resolved);
		Iterator<Ref> itr = map.values().iterator();
		try {
			itr.hasNext();
			fail("iterator did not catch bad input");
		} catch (IllegalStateException err) {
			// expected
		}
	}

	public void testMerge_HeadMaster() {
		final Ref master = newRef("refs/heads/master", ID_ONE);
		final Ref headU = newRef("HEAD", "refs/heads/master");
		final Ref headR = newRef("HEAD", master);

		loose = toList(headU, master);
		resolved = toList(headR);

		RefMap map = new RefMap("", packed, loose, resolved);
		assertEquals(2, map.size());
		assertFalse(map.isEmpty());
		assertTrue(map.containsKey("refs/heads/master"));
		assertSame(master, map.get("refs/heads/master"));

		// resolved overrides loose given same name
		assertSame(headR, map.get("HEAD"));

		Iterator<Ref> itr = map.values().iterator();
		assertTrue(itr.hasNext());
		assertSame(headR, itr.next());
		assertTrue(itr.hasNext());
		assertSame(master, itr.next());
		assertFalse(itr.hasNext());
	}

	public void testMerge_PackedLooseLoose() {
		final Ref refA = newRef("A", ID_ONE);
		final Ref refB_ONE = newRef("B", ID_ONE);
		final Ref refB_TWO = newRef("B", ID_TWO);
		final Ref refc = newRef("c", ID_ONE);

		packed = toList(refA, refB_ONE);
		loose = toList(refB_TWO, refc);

		RefMap map = new RefMap("", packed, loose, resolved);
		assertEquals(3, map.size());
		assertFalse(map.isEmpty());
		assertTrue(map.containsKey(refA.getName()));
		assertSame(refA, map.get(refA.getName()));

		// loose overrides packed given same name
		assertSame(refB_TWO, map.get(refB_ONE.getName()));

		Iterator<Ref> itr = map.values().iterator();
		assertTrue(itr.hasNext());
		assertSame(refA, itr.next());
		assertTrue(itr.hasNext());
		assertSame(refB_TWO, itr.next());
		assertTrue(itr.hasNext());
		assertSame(refc, itr.next());
		assertFalse(itr.hasNext());
	}

	public void testMerge_WithPrefix() {
		final Ref a = newRef("refs/heads/A", ID_ONE);
		final Ref b = newRef("refs/heads/foo/bar/B", ID_TWO);
		final Ref c = newRef("refs/heads/foo/rab/C", ID_TWO);
		final Ref g = newRef("refs/heads/g", ID_ONE);
		packed = toList(a, b, c, g);

		RefMap map = new RefMap("refs/heads/foo/", packed, loose, resolved);
		assertEquals(2, map.size());

		assertSame(b, map.get("bar/B"));
		assertSame(c, map.get("rab/C"));
		assertNull(map.get("refs/heads/foo/bar/B"));
		assertNull(map.get("refs/heads/A"));

		assertTrue(map.containsKey("bar/B"));
		assertTrue(map.containsKey("rab/C"));
		assertFalse(map.containsKey("refs/heads/foo/bar/B"));
		assertFalse(map.containsKey("refs/heads/A"));

		Iterator<Map.Entry<String, Ref>> itr = map.entrySet().iterator();
		Map.Entry<String, Ref> ent;
		assertTrue(itr.hasNext());
		ent = itr.next();
		assertEquals("bar/B", ent.getKey());
		assertSame(b, ent.getValue());
		assertTrue(itr.hasNext());
		ent = itr.next();
		assertEquals("rab/C", ent.getKey());
		assertSame(c, ent.getValue());
		assertFalse(itr.hasNext());
	}

	public void testPut_KeyMustMatchName_NoPrefix() {
		final Ref refA = newRef("refs/heads/A", ID_ONE);
		RefMap map = new RefMap("", packed, loose, resolved);
		try {
			map.put("FOO", refA);
			fail("map accepted invalid key/value pair");
		} catch (IllegalArgumentException err) {
			// expected
		}
	}

	public void testPut_KeyMustMatchName_WithPrefix() {
		final Ref refA = newRef("refs/heads/A", ID_ONE);
		RefMap map = new RefMap("refs/heads/", packed, loose, resolved);
		try {
			map.put("FOO", refA);
			fail("map accepted invalid key/value pair");
		} catch (IllegalArgumentException err) {
			// expected
		}
	}

	public void testPut_NoPrefix() {
		final Ref refA_one = newRef("refs/heads/A", ID_ONE);
		final Ref refA_two = newRef("refs/heads/A", ID_TWO);

		packed = toList(refA_one);

		RefMap map = new RefMap("", packed, loose, resolved);
		assertSame(refA_one, map.get(refA_one.getName()));
		assertSame(refA_one, map.put(refA_one.getName(), refA_two));

		// map changed, but packed, loose did not
		assertSame(refA_two, map.get(refA_one.getName()));
		assertSame(refA_one, packed.get(0));
		assertEquals(0, loose.size());

		assertSame(refA_two, map.put(refA_one.getName(), refA_one));
		assertSame(refA_one, map.get(refA_one.getName()));
	}

	public void testPut_WithPrefix() {
		final Ref refA_one = newRef("refs/heads/A", ID_ONE);
		final Ref refA_two = newRef("refs/heads/A", ID_TWO);

		packed = toList(refA_one);

		RefMap map = new RefMap("refs/heads/", packed, loose, resolved);
		assertSame(refA_one, map.get("A"));
		assertSame(refA_one, map.put("A", refA_two));

		// map changed, but packed, loose did not
		assertSame(refA_two, map.get("A"));
		assertSame(refA_one, packed.get(0));
		assertEquals(0, loose.size());

		assertSame(refA_two, map.put("A", refA_one));
		assertSame(refA_one, map.get("A"));
	}

	public void testPut_CollapseResolved() {
		final Ref master = newRef("refs/heads/master", ID_ONE);
		final Ref headU = newRef("HEAD", "refs/heads/master");
		final Ref headR = newRef("HEAD", master);
		final Ref a = newRef("refs/heads/A", ID_ONE);

		loose = toList(headU, master);
		resolved = toList(headR);

		RefMap map = new RefMap("", packed, loose, resolved);
		assertNull(map.put(a.getName(), a));
		assertSame(a, map.get(a.getName()));
		assertSame(headR, map.get("HEAD"));
	}

	public void testRemove() {
		final Ref master = newRef("refs/heads/master", ID_ONE);
		final Ref headU = newRef("HEAD", "refs/heads/master");
		final Ref headR = newRef("HEAD", master);

		packed = toList(master);
		loose = toList(headU, master);
		resolved = toList(headR);

		RefMap map = new RefMap("", packed, loose, resolved);
		assertNull(map.remove("not.a.reference"));

		assertSame(master, map.remove("refs/heads/master"));
		assertNull(map.get("refs/heads/master"));

		assertSame(headR, map.remove("HEAD"));
		assertNull(map.get("HEAD"));

		assertTrue(map.isEmpty());
	}

	public void testToString_NoPrefix() {
		final Ref a = newRef("refs/heads/A", ID_ONE);
		final Ref b = newRef("refs/heads/B", ID_TWO);

		packed = toList(a, b);

		StringBuilder exp = new StringBuilder();
		exp.append("[");
		exp.append(a.toString());
		exp.append(", ");
		exp.append(b.toString());
		exp.append("]");

		RefMap map = new RefMap("", packed, loose, resolved);
		assertEquals(exp.toString(), map.toString());
	}

	public void testToString_WithPrefix() {
		final Ref a = newRef("refs/heads/A", ID_ONE);
		final Ref b = newRef("refs/heads/foo/B", ID_TWO);
		final Ref c = newRef("refs/heads/foo/C", ID_TWO);
		final Ref g = newRef("refs/heads/g", ID_ONE);

		packed = toList(a, b, c, g);

		StringBuilder exp = new StringBuilder();
		exp.append("[");
		exp.append(b.toString());
		exp.append(", ");
		exp.append(c.toString());
		exp.append("]");

		RefMap map = new RefMap("refs/heads/foo/", packed, loose, resolved);
		assertEquals(exp.toString(), map.toString());
	}

	public void testEntryType() {
		final Ref a = newRef("refs/heads/A", ID_ONE);
		final Ref b = newRef("refs/heads/B", ID_TWO);

		packed = toList(a, b);

		RefMap map = new RefMap("refs/heads/", packed, loose, resolved);
		Iterator<Map.Entry<String, Ref>> itr = map.entrySet().iterator();
		Map.Entry<String, Ref> ent_a = itr.next();
		Map.Entry<String, Ref> ent_b = itr.next();

		assertEquals(ent_a.hashCode(), "A".hashCode());
		assertTrue(ent_a.equals(ent_a));
		assertFalse(ent_a.equals(ent_b));

		assertEquals(a.toString(), ent_a.toString());
	}

	public void testEntryTypeSet() {
		final Ref refA_one = newRef("refs/heads/A", ID_ONE);
		final Ref refA_two = newRef("refs/heads/A", ID_TWO);

		packed = toList(refA_one);

		RefMap map = new RefMap("refs/heads/", packed, loose, resolved);
		assertSame(refA_one, map.get("A"));

		Map.Entry<String, Ref> ent = map.entrySet().iterator().next();
		assertEquals("A", ent.getKey());
		assertSame(refA_one, ent.getValue());

		assertSame(refA_one, ent.setValue(refA_two));
		assertSame(refA_two, ent.getValue());
		assertSame(refA_two, map.get("A"));
		assertEquals(1, map.size());
	}

	private RefList<Ref> toList(Ref... refs) {
		RefList.Builder<Ref> b = new RefList.Builder<Ref>(refs.length);
		b.addAll(refs, 0, refs.length);
		return b.toRefList();
	}

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

	private static Ref newRef(String name, Ref dst) {
		return new SymbolicRef(name, dst);
	}

	private static Ref newRef(String name, ObjectId id) {
		return new ObjectIdRef.Unpeeled(Ref.Storage.LOOSE, name, id);
	}
}
