package core;

import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;

import core.Board;
import core.Direction;
import core.Pawn;

import exception.OutOfBoardException;
import exception.TakenSquareException;

public class TestPawn {

	private Board board;
	private Pawn pawn;
	private Pawn enemy;

	/**
	 * Crée deux pions sur un plateau de 3x4 cases, respectivement à la position
	 * (1, 2) et (0, 1). La case (1, 1) est une case "bonus".
	 */
	@Before
	public void initBoard() throws TakenSquareException, OutOfBoardException {
		board = new Board(3, 4, 1, 1);
		pawn = new Pawn('1', 1, 2, board);
		enemy = new Pawn('2', 0, 1, board);
		board.addPawn(pawn);
		board.addPawn(enemy);
	}

	/**
	 * Test du caractère représentant le pion
	 */
	@Test
	public void letter() {
		assertEquals('1', pawn.getLetter());
	}

	/**
	 * Test de la position x du pion
	 */
	@Test
	public void positionOnTheXAxis() {
		assertEquals(1, pawn.getX());
	}

	/**
	 * Test de la position y du pion
	 */
	@Test
	public void positionOnTheYAxis() {
		assertEquals(2, pawn.getY());
	}

	/**
	 * Test que le pion est vivant à sa création
	 */
	@Test
	public void initiallytAlive() {
		assertFalse(pawn.isDead());
	}

	/**
	 * Test des points de vie du pion à sa création
	 */
	@Test
	public void initialHitpoints() {
		assertEquals(2, pawn.getHitpoints());
	}

	/**
	 * Test du nombre de pièces d'or du pion à sa création
	 */
	@Test
	public void initialGold() {
		assertEquals(0, pawn.getGold());
	}

	/**
	 * Test d'un déplacement vers le haut qui reste dans le plateau
	 */
	@Test
	public void legalMoveUp() throws OutOfBoardException {
		pawn.move(Direction.HAUT);
		assertEquals(1, pawn.getX());
		assertEquals(3, pawn.getY());
	}

	/**
	 * Test d'un déplacement vers le haut qui sort du plateau
	 */
	@Test(expected = OutOfBoardException.class)
	public void illegalMoveUp() throws OutOfBoardException {
		pawn.move(Direction.HAUT);
		pawn.move(Direction.HAUT);
		;
	}

	/**
	 * Test d'un déplacement vers le bas qui reste dans le plateau
	 */
	@Test
	public void legalMoveDown() throws OutOfBoardException {
		pawn.move(Direction.BAS);
		pawn.move(Direction.BAS);
		assertEquals(1, pawn.getX());
		assertEquals(0, pawn.getY());
	}

	/**
	 * Test d'un déplacement vers le bas qui sort du plateau
	 */
	@Test(expected = OutOfBoardException.class)
	public void illegalMoveDown() throws OutOfBoardException {
		pawn.move(Direction.BAS);
		pawn.move(Direction.BAS);
		pawn.move(Direction.BAS);
	}

	/**
	 * Test d'un déplacement vers la gauche qui reste dans le plateau
	 */
	@Test
	public void legalMoveLeft() throws OutOfBoardException {
		pawn.move(Direction.GAUCHE);
		assertEquals(0, pawn.getX());
		assertEquals(2, pawn.getY());
	}

	/**
	 * Test d'un déplacement vers la gauche qui sort du plateau
	 */
	@Test(expected = OutOfBoardException.class)
	public void illegalMoveLeft() throws OutOfBoardException {
		pawn.move(Direction.GAUCHE);
		pawn.move(Direction.GAUCHE);
	}

	/**
	 * Test d'un déplacement vers la droite qui reste dans le plateau
	 */
	@Test
	public void legalMoveRight() throws OutOfBoardException {
		pawn.move(Direction.DROITE);
		assertEquals(2, pawn.getX());
		assertEquals(2, pawn.getY());
	}

	/**
	 * Test d'un déplacement vers la droite qui sort du plateau
	 */
	@Test(expected = OutOfBoardException.class)
	public void illegalMoveRight() throws OutOfBoardException {
		pawn.move(Direction.DROITE);
		pawn.move(Direction.DROITE);
	}

	/**
	 * Test de la blessure d'un pion ennemi sans être sur la case "bonus"
	 */
	@Test
	public void woundWithBonusSquare() throws OutOfBoardException {
		pawn.move(Direction.BAS);
		pawn.move(Direction.GAUCHE);
		assertEquals(0, this.enemy.getHitpoints());
		assertEquals(1, pawn.getX());
		assertEquals(1, pawn.getY());
	}

	/**
	 * Test de la blessure d'un pion ennemi en étant sur la case "bonus"
	 */
	@Test
	public void woundWithoutBonusSquare() throws OutOfBoardException {
		pawn.move(Direction.GAUCHE);
		pawn.move(Direction.BAS);
		assertEquals(1, enemy.getHitpoints());
		assertEquals(0, pawn.getX());
		assertEquals(2, pawn.getY());
	}

	/**
	 * Test de la mort d'un pion avec 0 point de vie
	 */
	@Test
	public void deadPawnWithZeroHitPoint() throws OutOfBoardException {
		pawn.move(Direction.BAS);
		pawn.move(Direction.GAUCHE);
		assertEquals(1, pawn.getGold());
		assertTrue(enemy.isDead());
		assertEquals(1, board.numberOfPawns());
		assertNull(board.getSquareContent(enemy.getX(), enemy.getY()));
	}
	
	/**
	 * Test de la mort d'un pion avec moins de 0 point de vie
	 */
	@Test
	public void deadPawnWithLessThanZeroHitPoint() throws OutOfBoardException {
		pawn.move(Direction.GAUCHE);
		pawn.move(Direction.BAS);
		pawn.move(Direction.DROITE);
		pawn.move(Direction.BAS);
		pawn.move(Direction.GAUCHE);
		assertEquals(1, pawn.getGold());
		assertTrue(enemy.isDead());
		assertEquals(1, board.numberOfPawns());
		assertNull(board.getSquareContent(enemy.getX(), enemy.getY()));
	}

}
