package ca.recrown.islandsurvivalcraft.caching;

import static org.junit.Assert.assertSame;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.AfterEach;
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;

@TestInstance(Lifecycle.PER_CLASS)
public class CacheTest {
    Cache<Integer> integerCache;

    @BeforeAll
    public void setUp() {
        integerCache = new Cache<>(3);
    }

    @AfterEach
    public void cleanUp() {
        integerCache.clearCache();
    }

    @Test
    public void testBasicCaching() {
        CoordinateIdentifier coordsA = new CoordinateIdentifier(3, 0);
        CoordinateIdentifier coordsB = new CoordinateIdentifier(4, 0);

        CacheValue<Integer> val = integerCache.retrieveCache(coordsA);
        assertTrue(val.isEmpty());
        val.setValue(0);
        assertFalse(val.isEmpty());
        assertSame(val, integerCache.retrieveCache(coordsA));

        val = integerCache.retrieveCache(coordsB);
        assertTrue(val.isEmpty());
        val.setValue(1);
        assertFalse(val.isEmpty());
        assertSame(val, integerCache.retrieveCache(coordsB));
    }

    @Test
    public void testUsageBasedClean() {
        integerCache.retrieveCache(new CoordinateIdentifier(1, 0)).setValue(1);
        integerCache.retrieveCache(new CoordinateIdentifier(2, 0)).setValue(2);
        integerCache.retrieveCache(new CoordinateIdentifier(3, 0)).setValue(3);
        
        integerCache.retrieveCache(new CoordinateIdentifier(1, 0)).getValue();

        integerCache.retrieveCache(new CoordinateIdentifier(4, 0)).setValue(4);
        
        assertEquals(1, integerCache.retrieveCache(new CoordinateIdentifier(1, 0)).getValue());

        assertFalse(integerCache.retrieveCache(new CoordinateIdentifier(1, 0)).isEmpty());

        integerCache.retrieveCache(new CoordinateIdentifier(5, 0)).setValue(5);
        assertFalse(integerCache.retrieveCache(new CoordinateIdentifier(1, 0)).isEmpty());
    }
}