////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////

package pp.battleship.model;

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

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

public class BattleshipTest {
    private Battleship ship;

    @Before
    public void setUp() {
        ship = new Battleship(3, 2, 2, Rotation.RIGHT);
    }

    @Test
    public void testDefaultConstructor() {
        Battleship defaultShip = new Battleship(1, 0, 0, Rotation.RIGHT);
        assertEquals(1, defaultShip.getLength());
        assertEquals(0, defaultShip.getX());
        assertEquals(0, defaultShip.getY());
        assertEquals(Rotation.RIGHT, defaultShip.getRot());
        assertEquals(Battleship.Status.NORMAL, defaultShip.getStatus());
    }

    @Test
    public void testConstructorWithParameters() {
        assertEquals(3, ship.getLength());
        assertEquals(2, ship.getX());
        assertEquals(2, ship.getY());
        assertEquals(Rotation.RIGHT, ship.getRot());
        assertEquals(Battleship.Status.NORMAL, ship.getStatus());
    }

    @Test
    public void testSetPosition() {
        ship.moveTo(4, 5);
        assertEquals(4, ship.getX());
        assertEquals(5, ship.getY());
    }

    @Test
    public void testSetPositionWithIntPosition() {
        IntPoint pos = p(5, 6);
        ship.moveTo(pos);
        assertEquals(5, ship.getX());
        assertEquals(6, ship.getY());
    }

    @Test
    public void testGetStatus() {
        assertEquals(Battleship.Status.NORMAL, ship.getStatus());
    }

    @Test
    public void testWithStatus() {
        ship.setStatus(Battleship.Status.VALID_PREVIEW);
        assertEquals(Battleship.Status.VALID_PREVIEW, ship.getStatus());
    }

    @Test
    public void testGetLength() {
        assertEquals(3, ship.getLength());
    }

    @Test
    public void testGetMinX() {
        assertEquals(2, ship.getMinX());
    }

    @Test
    public void testGetMaxX() {
        assertEquals(4, ship.getMaxX());
    }

    @Test
    public void testGetMaxY() {
        assertEquals(2, ship.getMaxY());
    }

    @Test
    public void testGetMinY() {
        assertEquals(2, ship.getMinY());
    }

    @Test
    public void testGetRotation() {
        assertEquals(Rotation.RIGHT, ship.getRot());
    }

    @Test
    public void testSetRotation() {
        ship.setRotation(Rotation.DOWN);
        assertEquals(Rotation.DOWN, ship.getRot());
    }

    @Test
    public void testRotated() {
        ship.rotated();
        assertEquals(Rotation.DOWN, ship.getRot());
    }

    @Test
    public void testHit() {
        assertTrue(ship.hit(2, 2));
        assertTrue(ship.hit(2, 2));
    }

    @Test
    public void testContains() {
        IntPoint pos = p(3, 2);
        assertTrue(ship.contains(pos));
    }

    @Test
    public void testIsDestroyed() {
        ship.hit(2, 2);
        ship.hit(3, 2);
        ship.hit(4, 2);
        assertTrue(ship.isDestroyed());
    }

    @Test
    public void testCollidesWith() {
        Battleship otherShip = new Battleship(3, 3, 2, Rotation.RIGHT);
        assertTrue(ship.collidesWith(otherShip));
    }

    @Test
    public void testToString() {
        assertEquals("Ship{length=3, x=2, y=2, rot=RIGHT}", ship.toString());
    }

    static IntPoint p(int x, int y) {
        return new IntPoint(x, y);
    }
}
