/*******************************************************************************
 * Copyright (c) 2000, 2017 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Alexander Kurtakov <akurtako@redhat.com> - Bug 459343
 *******************************************************************************/
package org.eclipse.core.tests.resources;

import java.util.Arrays;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.core.internal.resources.*;
import org.eclipse.core.resources.IMarker;

public class MarkerSetTest extends ResourceTest {

	/**
	 * Need a zero argument constructor to satisfy the test harness.
	 * This constructor should not do any real work nor should it be
	 * called by user code.
	 */
	public MarkerSetTest() {
		super();
	}

	/**
	 * Creates a new markers test.
	 */
	public MarkerSetTest(String name) {
		super(name);
	}

	public void assertEquals(String message, IMarkerSetElement[] array1, IMarkerSetElement[] array2) {
		assertNotNull(message, array1);
		assertNotNull(message, array2);
		assertEquals(message, array1.length, array2.length);
		IMarkerSetElement[] m1 = new IMarkerSetElement[array1.length];
		System.arraycopy(array1, 0, m1, 0, array1.length);
		IMarkerSetElement[] m2 = new IMarkerSetElement[array2.length];
		System.arraycopy(array2, 0, m2, 0, array2.length);
		java.util.Comparator<IMarkerSetElement> compare = (e1, e2) -> {
			long id1 = e1.getId();
			long id2 = e2.getId();
			if (id1 == id2) {
				return 0;
			}
			return id1 < id2 ? -1 : 1;
		};
		Arrays.sort(m1, compare);
		Arrays.sort(m2, compare);
		for (int i = 0; i < m1.length; i++) {
			assertEquals(message, m1[i].getId(), m2[i].getId());
		}
	}

	/**
	 * Configures the markers test suite.
	 */
	public static Test suite() {
		return new TestSuite(MarkerSetTest.class);

		//TestSuite suite = new TestSuite();
		//suite.addTest(new MarkerSetTest("_testPR"));
		//return suite;
	}

	public void testAdd() {

		// create the objects to insert into the set
		MarkerSet set = new MarkerSet();
		int max = 100;
		MarkerInfo info = null;
		MarkerInfo[] infos = new MarkerInfo[max];
		for (int i = 0; i < max; i++) {
			info = new MarkerInfo();
			info.setId(i);
			info.setType(IMarker.PROBLEM);
			info.setAttribute(IMarker.MESSAGE, getRandomString(), true);
			infos[i] = info;
		}

		// add each info to the set
		for (int i = 0; i < infos.length; i++) {
			info = infos[i];
			set.add(info);
			assertTrue("2.0." + i, set.contains(info.getId()));
			assertEquals("2.1." + i, i + 1, set.size());
		}

		// make sure they are all still there
		assertEquals("3.0", max, set.size());
		for (int i = 0; i < infos.length; i++) {
			info = infos[i];
			assertTrue("3.1." + i, set.contains(info.getId()));
			assertNotNull("3.2." + i, set.get(info.getId()));
		}
	}

	public void testElements() {

		// populate the set
		MarkerSet set = new MarkerSet();
		int max = 100;
		MarkerInfo info = null;
		MarkerInfo[] infos = new MarkerInfo[max];
		for (int i = 0; i < max; i++) {
			info = new MarkerInfo();
			info.setId(i);
			info.setType(IMarker.PROBLEM);
			info.setAttribute(IMarker.MESSAGE, getRandomString(), true);
			infos[i] = info;
		}
		set.addAll(infos);
		assertEquals("1.0", max, set.size());

		// remove each element
		assertEquals("2.0", set.elements(), infos);
	}

	public void testRemove() {

		// populate the set
		MarkerSet set = new MarkerSet();
		int max = 100;
		MarkerInfo info = null;
		MarkerInfo[] infos = new MarkerInfo[max];
		for (int i = 0; i < max; i++) {
			info = new MarkerInfo();
			info.setId(i);
			info.setType(IMarker.PROBLEM);
			info.setAttribute(IMarker.MESSAGE, getRandomString(), true);
			infos[i] = info;
		}
		set.addAll(infos);
		assertEquals("1.0", max, set.size());

		// remove each element
		for (int i = max - 1; i >= 0; i--) {
			info = infos[i];
			set.remove(info);
			assertTrue("2.0." + i, !set.contains(info.getId()));
			assertEquals("2.1," + i, i, set.size());
			// check that the others still exist
			for (int j = 0; j < i; j++) {
				assertTrue("2.2." + j, set.contains(infos[j].getId()));
			}
		}

		// all gone?
		assertEquals("3.0", 0, set.size());
	}
}
