import junit.framework.TestCase;
/*
 * Created on Oct 13, 2007
 */

public class OceanTest extends TestCase {
    private final int OCEAN_SIZE = 10;
    private final int BATTLESHIP_LENGTH = 4;
    private final int CRUISER_LENGTH = 3;
    private final int DESTROYER_LENGTH = 2;
    private final int SUBMARINE_LENGTH = 1;

    Ocean ocean;

    protected void setUp() throws Exception {
        super.setUp();
        ocean = new Ocean();
        ocean.placeSubmarineAt(0, 0);
        ocean.placeSubmarineAt(2, 4);
    }
    
    public OceanTest(String name) {
        super(name);
    }

    public final void testOcean() {
        ocean = new Ocean();
        assertEquals(0, numberOfSquaresOccupied());
        assertEquals(0, ocean.numberOfShotsFired());
        assertEquals(0, ocean.numberOfHits());
    }

    public final void testPlaceAllShipsRandomly() {
        ocean = new Ocean();
        ocean.placeAllShipsRandomly();
        assertEquals(20, numberOfSquaresOccupied());
    }
    
    public final void testPlaceAllShipsRandomlyManyTimes() {
        int count = 0;
        int limit = 1000;
        for (int i = 0; i < limit; i++) {
            ocean = new Ocean();
            ocean.placeAllShipsRandomly();
        }
    }

    public final void testOkToPlaceBattleshipAt() {
        assertFalse(ocean.okToPlaceBattleshipAt(0, 0, true));
        assertFalse(ocean.okToPlaceBattleshipAt(0, 1, false));
        assertFalse(ocean.okToPlaceBattleshipAt(1, 0, true));
        assertFalse(ocean.okToPlaceBattleshipAt(1, 1, false));

        assertTrue(ocean.okToPlaceBattleshipAt(0, 2, true));
        assertTrue(ocean.okToPlaceBattleshipAt(0, 2, false));

        assertTrue(ocean.okToPlaceBattleshipAt(0, 6, true));
        assertFalse(ocean.okToPlaceBattleshipAt(0, 7, true));
        assertTrue(ocean.okToPlaceBattleshipAt(6, 0, false));
        assertFalse(ocean.okToPlaceBattleshipAt(7, 0, false));
        assertFalse(ocean.okToPlaceBattleshipAt(9, 9, true));
        }

    public final void testPlaceBattleshipAt() {
        int count = numberOfSquaresOccupied();
        ocean.placeBattleshipAt(9, 6, true);
        assertEquals(count + BATTLESHIP_LENGTH, numberOfSquaresOccupied());
        ocean.placeBattleshipAt(2, 9, false);
        assertEquals(count + 2 * BATTLESHIP_LENGTH, numberOfSquaresOccupied());
    }

    public final void testOkToPlaceCruiserAt() {
        assertFalse(ocean.okToPlaceCruiserAt(0, 0, true));
        assertFalse(ocean.okToPlaceCruiserAt(0, 1, false));
        assertFalse(ocean.okToPlaceCruiserAt(1, 0, true));
        assertFalse(ocean.okToPlaceCruiserAt(1, 1, false));

        assertTrue(ocean.okToPlaceCruiserAt(0, 2, true));
        assertTrue(ocean.okToPlaceCruiserAt(0, 2, false));

        assertTrue(ocean.okToPlaceCruiserAt(0, 7, true));
        assertFalse(ocean.okToPlaceCruiserAt(0, 8, true));
        assertTrue(ocean.okToPlaceCruiserAt(7, 0, false));
        assertFalse(ocean.okToPlaceCruiserAt(8, 0, false));
        assertFalse(ocean.okToPlaceCruiserAt(9, 9, true));
    }

    public final void testPlaceCruiserAt() {
        int count = numberOfSquaresOccupied();
        ocean.placeCruiserAt(9, 6, true);
        assertEquals(count + CRUISER_LENGTH, numberOfSquaresOccupied());
        ocean.placeCruiserAt(2, 9, false);
        assertEquals(count + 2 * CRUISER_LENGTH, numberOfSquaresOccupied());
    }

    public final void testOkToPlaceDestroyerAt() {
        assertFalse(ocean.okToPlaceDestroyerAt(0, 0, true));
        assertFalse(ocean.okToPlaceDestroyerAt(0, 1, false));
        assertFalse(ocean.okToPlaceDestroyerAt(1, 0, true));
        assertFalse(ocean.okToPlaceDestroyerAt(1, 1, false));

        assertTrue(ocean.okToPlaceDestroyerAt(0, 2, true));
        assertTrue(ocean.okToPlaceDestroyerAt(0, 2, false));

        assertTrue(ocean.okToPlaceDestroyerAt(0, 8, true));
        assertFalse(ocean.okToPlaceDestroyerAt(0, 9, true));
        assertTrue(ocean.okToPlaceDestroyerAt(8, 0, false));
        assertFalse(ocean.okToPlaceDestroyerAt(9, 0, false));
        assertFalse(ocean.okToPlaceDestroyerAt(9, 9, true));
    }

    public final void testPlaceDestroyerAt() {
        int count = numberOfSquaresOccupied();
        ocean.placeDestroyerAt(9, 6, true);
        assertEquals(count + DESTROYER_LENGTH, numberOfSquaresOccupied());
        ocean.placeDestroyerAt(2, 9, false);
        assertEquals(count + 2 * DESTROYER_LENGTH, numberOfSquaresOccupied());
    }

    public final void testOkToPlaceSubmarineAt() {
        assertFalse(ocean.okToPlaceSubmarineAt(0, 0));
        assertFalse(ocean.okToPlaceSubmarineAt(0, 1));
        assertFalse(ocean.okToPlaceSubmarineAt(1, 0));
        assertFalse(ocean.okToPlaceSubmarineAt(1, 1));

        assertTrue(ocean.okToPlaceSubmarineAt(1, 2));
        assertTrue(ocean.okToPlaceSubmarineAt(9, 9));
    }

    public final void testPlaceSubmarineAt() {
        assertTrue(ocean.okToPlaceSubmarineAt(6, 8));
        assertFalse(ocean.isOccupied(6, 8));
        ocean.placeSubmarineAt(6, 8);
        for (int i = 5; i <= 7; i++) {
            for (int j = 7; j <= 9; j++) {
                assertEquals(ocean.isOccupied(i, j), i == 6 && j == 8);
            }
        }
        int count = numberOfSquaresOccupied();
        ocean.placeSubmarineAt(9, 6);
        assertEquals(count + SUBMARINE_LENGTH, numberOfSquaresOccupied());
        ocean.placeSubmarineAt(2, 9);
        assertEquals(count + 2 * SUBMARINE_LENGTH, numberOfSquaresOccupied());
    }

    public final void testIsOccupied() {
        for (int i = 0; i < OCEAN_SIZE; i++) {
            for (int j = 0; j < OCEAN_SIZE; j++) {
                if (i == 0 && j == 0) assertTrue(ocean.isOccupied(i, j));
                else if (i == 2 && j == 4) assertTrue(ocean.isOccupied(i, j));
                else assertFalse(ocean.isOccupied(i, j));
            }
        }
    }

    public final void testShootAt() {
        assertTrue(ocean.shootAt(0, 0));
        assertTrue(ocean.shootAt(2, 4));
        assertTrue(ocean.shootAt(0, 0));
        assertFalse(ocean.shootAt(4, 4));
        assertFalse(ocean.shootAt(4, 2));
    }

    public final void testNumberOfShotsFired() {
        assertEquals(0, ocean.numberOfShotsFired());
        ocean.shootAt(0, 0);
        assertEquals(1, ocean.numberOfShotsFired());
        ocean.shootAt(9, 9);
        assertEquals(2, ocean.numberOfShotsFired());
        ocean.shootAt(0, 0);
        assertEquals(3, ocean.numberOfShotsFired());
    }

    public final void testNumberOfHits() {
        assertEquals(0, ocean.numberOfHits());
        ocean.shootAt(0, 1);
        assertEquals(0, ocean.numberOfHits());
        ocean.shootAt(1, 0);
        assertEquals(0, ocean.numberOfHits());
        ocean.shootAt(0, 0);
        assertEquals(1, ocean.numberOfHits());
        ocean.shootAt(2, 4);
        assertEquals(2, ocean.numberOfHits());
        ocean.shootAt(0, 0);
        assertEquals(3, ocean.numberOfHits());
    }

    public final void testIsGameOver() {
        assertFalse(ocean.isGameOver());
        ocean.shootAt(0, 0);
        assertFalse(ocean.isGameOver());
        ocean.shootAt(0, 0);
        assertFalse(ocean.isGameOver());
        ocean.shootAt(8, 8);
        assertFalse(ocean.isGameOver());
        ocean.shootAt(2, 4);
        assertTrue(ocean.isGameOver());
    }

    private int numberOfSquaresOccupied() {
        int count = 0;
        for (int i = 0; i < OCEAN_SIZE; i++) {
            for (int j = 0; j < OCEAN_SIZE; j++) {
                if (ocean.isOccupied(i, j)) count++;
            }
        }
        return count;
    }
}
