package ca.recrown.islandsurvivalcraft.world;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.Random;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;

import ca.recrown.islandsurvivalcraft.utilities.datatypes.Point2;

@TestInstance(Lifecycle.PER_CLASS)
public class IslandWorldMapTest {
    public final int SEED = 102385923;
    public final int GRIDSIZE = 2048;
    public Random random = new Random(SEED);
    public IslandWorldMap mapper = new IslandWorldMap(random);
    public final double[][] answers = new double[GRIDSIZE][GRIDSIZE];

    @BeforeAll
    public void setUp() {
        for (int x = 0; x < answers.length; x++) {
            for (int y = 0; y < answers[x].length; y++) {
                answers[x][y] = mapper.getWorldValue(x, y);
            }
        }
    }

    @Test
    public void testBlockValueConsistency() {
        for (int x = 0; x < answers.length; x++) {
            for (int y = 0; y < answers[x].length; y++) {
                assertEquals(answers[x][y], mapper.getWorldValue(x, y), String.format("Occurred at (%d, %d)", x, y));
            }
        }
    }

    @Test
    public void testBlockValueConsistencyRandom() {
        for (int amount = 0; amount < GRIDSIZE; amount++) {
            int x = random.nextInt(answers.length);
            int y = random.nextInt(answers[x].length);
            assertEquals(answers[x][y], mapper.getWorldValue(x, y), String.format("Occurred at (%d, %d)", x, y));
        }
    }
    
    @Test
    public void testValuesValidity() {
        for (int i = 0; i < 1024; i++) {
            int x = random.nextInt();
            int y = random.nextInt();
            assertTrue((mapper.getWorldValue(x, y) <= 1));
            assertTrue((mapper.getWorldValue(x, y) >= -1));
        }
    }

    @Test
    public void testIslandOriginConsistency() {
        Point2 origin = null;
        for (int i = 0; i < GRIDSIZE; i++) {
            if (origin != null) {
                if (mapper.isSameIsland(origin.x, origin.y, i, 0)) {
                    assertEquals(origin, mapper.findIslandOrigin(i, 0), String.format("Looking at (%d, 0)", i));
                } else {
                    origin = null;
                }
            } else if (mapper.isIsland(i, 0)) {
                origin = mapper.findIslandOrigin(i, 0);
            }
        }
    }

    @Test
    public void testIslandOriginConsistency2D() {
        int gridSize = 32;
        Point2 origin = null;
        for (int y = 0; y < gridSize; y++) {
            for (int x = 0; x < gridSize; x++) {
                if (origin != null) {
                    if (mapper.isSameIsland(origin.x, origin.y, x, y)) {
                        assertEquals(origin, mapper.findIslandOrigin(x, y), String.format("Looking at (%d, %d)", x, y));
                    } else {
                        origin = null;
                    }
                } else if (mapper.isIsland(x, y)) {
                    origin = mapper.findIslandOrigin(x, y);
                }
            }
        }
    }
}