package ashley.core;

import static org.junit.Assert.*;

import java.util.BitSet;
import java.util.HashSet;
import java.util.Set;

import org.junit.Test;

import ashley.core.Component;
import ashley.core.ComponentType;
import ashley.core.Entity;
import ashley.signals.Listener;
import ashley.signals.Signal;
import ashley.utils.Array;

public class EntityTests {

	private static class ComponentA extends Component {
		
	}
	
	private static class ComponentB extends Component {
		
	}
	
	private static class EntityListenerMock implements Listener<Entity> {

		public int counter = 0;
		
		@Override
		public void receive(Signal<Entity> signal, Entity object) {
			++counter;
			
			assertNotNull(signal);
			assertNotNull(object);
		}
	}
	
	@Test
	public void uniqueIndex() {
		int numEntities = 10000;
		Array<Entity> entities = new Array<Entity>();
		Set<Integer> ids = new HashSet<Integer>();
		
		for (int i = 0; i < numEntities; ++i) {
			Entity entity = new Entity();
			assertFalse(ids.contains(entity.getIndex()));
			ids.add(entity.getIndex());
			entities.add(entity);
		}
	}
	
	@Test
	public void noComponents() {
		Entity entity = new Entity();
		
		assertEquals(0, entity.getComponents().getSize());
		
		BitSet componentBits = entity.getComponentBits();
		
		for (int i = 0; i < componentBits.size(); ++i) {
			assertEquals(false, componentBits.get(i));
		}
		
		assertNull(entity.getComponent(ComponentA.class));
		assertNull(entity.getComponent(ComponentB.class));
		assertFalse(entity.hasComponent(ComponentA.class));
		assertFalse(entity.hasComponent(ComponentB.class));
	}
	
	@Test
	public void addAndRemoveComponent() {
		Entity entity = new Entity();
		
		entity.add(new ComponentA());
		
		assertEquals(1, entity.getComponents().getSize());
		
		BitSet componentBits = entity.getComponentBits();
		int componentAIndex = ComponentType.getIndexFor(ComponentA.class);
		
		for (int i = 0; i < componentBits.size(); ++i) {
			assertEquals(i == componentAIndex, componentBits.get(i));
		}
		
		assertNotNull(entity.getComponent(ComponentA.class));
		assertNull(entity.getComponent(ComponentB.class));
		assertTrue(entity.hasComponent(ComponentA.class));
		assertFalse(entity.hasComponent(ComponentB.class));
		
		entity.remove(ComponentA.class);
		
		assertEquals(0, entity.getComponents().getSize());
		
		for (int i = 0; i < componentBits.size(); ++i) {
			assertFalse(componentBits.get(i));
		}
		
		assertNull(entity.getComponent(ComponentA.class));
		assertNull(entity.getComponent(ComponentB.class));
		assertFalse(entity.hasComponent(ComponentA.class));
		assertFalse(entity.hasComponent(ComponentB.class));
	}
	
	@Test
	public void addAndRemoveComponents() {
		Entity entity = new Entity();
		
		entity.add(new ComponentA());
		entity.add(new ComponentB());
		
		assertEquals(2, entity.getComponents().getSize());
		
		BitSet componentBits = entity.getComponentBits();
		int componentAIndex = ComponentType.getIndexFor(ComponentA.class);
		int componentBIndex = ComponentType.getIndexFor(ComponentB.class);
		
		for (int i = 0; i < componentBits.size(); ++i) {
			assertEquals(i == componentAIndex || i == componentBIndex, componentBits.get(i));
		}
		
		assertNotNull(entity.getComponent(ComponentA.class));
		assertNotNull(entity.getComponent(ComponentB.class));
		assertTrue(entity.hasComponent(ComponentA.class));
		assertTrue(entity.hasComponent(ComponentB.class));
		
		entity.removeAll();
		
		assertEquals(0, entity.getComponents().getSize());
		
		for (int i = 0; i < componentBits.size(); ++i) {
			assertFalse(componentBits.get(i));
		}
		
		assertNull(entity.getComponent(ComponentA.class));
		assertNull(entity.getComponent(ComponentB.class));
		assertFalse(entity.hasComponent(ComponentA.class));
		assertFalse(entity.hasComponent(ComponentB.class));
	}
	
	@Test
	public void addSameComponent() {
		Entity entity = new Entity();
		
		entity.add(new ComponentA());
		entity.add(new ComponentA());
		
		assertEquals(1, entity.getComponents().getSize());
		assertTrue(entity.hasComponent(ComponentA.class));
	}
	
	@Test
	public void componentListener() {
		EntityListenerMock addedListener = new EntityListenerMock();
		EntityListenerMock removedListener = new EntityListenerMock();
		
		Entity entity = new Entity();
		entity.componentAdded.add(addedListener);
		entity.componentRemoved.add(removedListener);
		
		assertEquals(0, addedListener.counter);
		assertEquals(0, removedListener.counter);
			
		entity.add(new ComponentA());
		
		assertEquals(1, addedListener.counter);
		assertEquals(0, removedListener.counter);
		
		entity.remove(ComponentA.class);
		
		assertEquals(1, addedListener.counter);
		assertEquals(1, removedListener.counter);
		
		entity.add(new ComponentB());
		
		assertEquals(2, addedListener.counter);
		
		entity.remove(ComponentB.class);
		
		assertEquals(2, removedListener.counter);
	}
}

@@ -401,37 +401,32 @@
 ends Component %7B
-%0A%09%09%0A%09
 %7D%0A%09%0A%09private sta
@@ -465,21 +465,16 @@
 ponent %7B
-%0A%09%09%0A%09
 %7D%0A%09%0A%09pri
@@ -1202,167 +1202,56 @@
 ;%0A%09%09
-%0A%09%09BitSet componentBits = entity.getComponentBits();%0A%09%09%0A%09%09for (int i = 0; i %3C componentBits.size(); ++i) %7B%0A%09%09%09assertEquals(false, componentBits.get(i));%0A%09%09%7D%0A%09%09
+assertTrue(entity.getComponentBits().isEmpty());
 %0A%09%09a
@@ -2533,32 +2533,35 @@
 oid addAndRemove
+All
 Components() %7B%0A%09
@@ -3744,35 +3744,40 @@
 ity();%0A%09%09%0A%09%09
-entity.add(
+ComponentA a1 = 
 new Componen
@@ -3784,40 +3784,82 @@
 tA()
-)
 ;%0A%09%09
-entity.add(new ComponentA()
+ComponentA a2 = new ComponentA();%0A%09%09%0A%09%09entity.add(a1);%0A%09%09entity.add(a2
 );%0A%09
@@ -3958,32 +3958,153 @@
 onentA.class));%0A
+%09%09assertNotEquals(a1, entity.getComponent(ComponentA.class));%0A%09%09assertEquals(a2, entity.getComponent(ComponentA.class));%0A
 %09%7D%0A%09%0A%09@Test%0A%09pub

refactor entity tests