import static org.junit.Assert.*;

import inf101.v18.rogue101.objects.IItem;
import org.junit.Test;

import inf101.v18.grid.ILocation;
import inf101.v18.rogue101.map.GameMap;

import java.util.List;

public class GameMapTest {

	@Test
	public void testSortedAdd() {
		GameMap gameMap = new GameMap(20, 20);
		ILocation location = gameMap.getLocation(10, 10);
		for (int i = 0; i < 30; i++) {
			gameMap.addRandomItems(location);
		}
		List<IItem> items = gameMap.getAll(location);
		for (int i = 0; i < items.size() - 1; i++) {
			assertTrue(items.get(i).compareTo(items.get(i + 1)) >= 0);
		}
	}

	@Test
	public void testGetNeighbours() {
		GameMap gameMap = new GameMap(20, 20);
		ILocation location = gameMap.getLocation(10, 10);

		List<ILocation> neighbours = gameMap.getNeighbourhood(location, 1);
		for (ILocation neighbour : neighbours) {
			assertTrue(location.gridDistanceTo(neighbour) <= 1);
		}
		assertEquals(8, neighbours.size());

		neighbours = gameMap.getNeighbourhood(location, 2);
		for (ILocation neighbour : neighbours) {
			assertTrue(location.gridDistanceTo(neighbour) <= 2);
		}
		assertEquals(24, neighbours.size());

		neighbours = gameMap.getNeighbourhood(location, 3);
		for (ILocation neighbour : neighbours) {
			assertTrue(location.gridDistanceTo(neighbour) <= 3);
		}
		assertEquals(48, neighbours.size());
	}

	@Test
	public void testNeighboursOutOfBounds() {
		//This is a bit overkill, but it's meant to distinguish between kind of working and always working.

		GameMap gameMap = new GameMap(20, 20);

		ILocation location = gameMap.getLocation(0, 0);
		List<ILocation> neighbours = gameMap.getNeighbourhood(location, 3);
		for (ILocation neighbour : neighbours) {
			assertTrue(location.gridDistanceTo(neighbour) <= 3);
		}
		assertEquals(15, neighbours.size());

		location = gameMap.getLocation(19, 0);
		neighbours = gameMap.getNeighbourhood(location, 3);
		for (ILocation neighbour : neighbours) {
			assertTrue(location.gridDistanceTo(neighbour) <= 3);
		}
		assertEquals(15, neighbours.size());

		location = gameMap.getLocation(19, 19);
		neighbours = gameMap.getNeighbourhood(location, 3);
		for (ILocation neighbour : neighbours) {
			assertTrue(location.gridDistanceTo(neighbour) <= 3);
		}
		assertEquals(15, neighbours.size());

		location = gameMap.getLocation(0, 19);
		neighbours = gameMap.getNeighbourhood(location, 3);
		for (ILocation neighbour : neighbours) {
			assertTrue(location.gridDistanceTo(neighbour) <= 3);
		}
		assertEquals(15, neighbours.size());

		location = gameMap.getLocation(0, 10);
		neighbours = gameMap.getNeighbourhood(location, 3);
		for (ILocation neighbour : neighbours) {
			assertTrue(location.gridDistanceTo(neighbour) <= 3);
		}
		assertEquals(27, neighbours.size());

		location = gameMap.getLocation(19, 10);
		neighbours = gameMap.getNeighbourhood(location, 3);
		for (ILocation neighbour : neighbours) {
			assertTrue(location.gridDistanceTo(neighbour) <= 3);
		}
		assertEquals(27, neighbours.size());

		location = gameMap.getLocation(10, 0);
		neighbours = gameMap.getNeighbourhood(location, 3);
		for (ILocation neighbour : neighbours) {
			assertTrue(location.gridDistanceTo(neighbour) <= 3);
		}
		assertEquals(27, neighbours.size());

		location = gameMap.getLocation(10, 19);
		neighbours = gameMap.getNeighbourhood(location, 3);
		for (ILocation neighbour : neighbours) {
			assertTrue(location.gridDistanceTo(neighbour) <= 3);
		}
		assertEquals(27, neighbours.size());
	}
}
