/*
 * @author Ranides Atterwim <ranides@gmail.com>
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */
package net.ranides.assira.collection;

import java.util.NoSuchElementException;
import org.junit.Test;
import static org.junit.Assert.*;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
@SuppressWarnings("PMD.AvoidDuplicateLiterals")
public class GridTest {
    
    private static final String NEE = "Exception expected";
    
    public GridTest() {
    }

    @Test
    public void testBuilder() {
        Grid<Integer> grid = new Grid<>()
            .header("x","y", "z")
            .add(1,2,3)
            .add(2,2,3)
            .add(3,2,3)
            .add(4,2,3)
            .add(5,2,3);
        
        assertEquals(5, grid.rows().size());
        assertEquals(3, grid.header().size());
        
        try {
            new Grid().header("x","y", "z").add(1,2,3,4);
            fail(NEE);
        } catch(IllegalArgumentException cause) {
            assertNotNull(cause);
        }
        
        try {
            new Grid().header("x","y", "z").add(1,2);
            fail(NEE);
        } catch(IllegalArgumentException cause) {
            assertNotNull(cause);
        }
        
        try {
            new Grid().add(1,2,3,4);
            fail(NEE);
        } catch(IllegalStateException cause) {
            assertNotNull(cause);
        }
        
        try {
            new Grid().header("x","y", "z").header("x","y");
            fail(NEE);
        } catch(IllegalStateException cause) {
            assertNotNull(cause);
        }
        
        try {
            new Grid().header();
            fail(NEE);
        } catch(IllegalStateException cause) {
            assertNotNull(cause);
        }
        
        try {
            new Grid().rows();
            fail(NEE);
        } catch(IllegalStateException cause) {
            assertNotNull(cause);
        }
        
        try {
            new Grid().column("key");
            fail(NEE);
        } catch(IllegalStateException cause) {
            assertNotNull(cause);
        }
    }
    
    @Test
    public void testHeader() {
        Grid<Integer> grid = new Grid<>()
            .header("x","y", "z")
            .add(1,2,3)
            .add(4,5,6);
        
        assertEquals("y", grid.header().get(1));
        assertArrayEquals(new String[]{"x","y","z"}, grid.header().toArray(new String[3]));
        
        grid.header().set(0, "X");
        grid.header().set(1, "Y");
        grid.header().set(2, "Z");
        
        assertEquals(4, (int)grid.rows().get(1).get("X"));
        assertEquals(5, (int)grid.rows().get(1).get("Y"));
        
        grid.header().set(0, "A");
        grid.header().set(1, "B");
        
        assertEquals(4, (int)grid.rows().get(1).get("A"));
        assertEquals(5, (int)grid.rows().get(1).get("B"));
        
        try {
            grid.rows().get(1).get("X");
            fail("UnsupportedOperationException expected");
        } catch(NoSuchElementException ex) {
            assertNotNull(ex);
        }
        
        try {
            grid.header().add("U");
            fail("UnsupportedOperationException expected");
        } catch(UnsupportedOperationException ex) {
            assertNotNull(ex);
        }
    }
    
    @Test
    public void testReads() {
        Grid<Integer> grid = new Grid<>()
            .header("x","y", "z")
            .add(10,11,12)
            .add(20,21,22)
            .add(30,31,32)
            .add(40,41,42)
            .add(50,51,52);
        
        assertEquals(3, grid.rows().get(3).size() );
        assertEquals(41, (int)grid.rows().get(3).get(1) );
        assertEquals(41, (int)grid.rows().get(3).get("y") );
        
        Integer expected[] = new Integer[]{12, 22, 32, 42, 52};
        Grid.Column<Integer> c = grid.column("z", Integer.class);
        for(int i=0; i<expected.length; i++) {
            assertEquals(expected[i], c.get(i));
        }
        
        assertArrayEquals(expected, c.toArray(new Integer[c.size()]));
        
        Object expected2[] = new Object[]{12, 22, 32, 42, 52};
        Grid.Column<Integer> c2 = grid.column("z");
        for(int i=0; i<expected2.length; i++) {
            assertEquals(expected2[i], c2.get(i));
        }
        
        assertArrayEquals(expected, c2.toArray(new Object[c.size()]));
    }
    
    @Test
    public void testWrites() {
        Grid<Integer> grid = new Grid<>()
            .header("x","y", "z")
            .add(10,11,12)
            .add(20,21,22)
            .add(30,31,32)
            .add(40,41,42)
            .add(50,51,52);
        grid.rows().get(1).set("x", 71);
        grid.rows().get(1).set(1, 72);
        
        assertArrayEquals(new Object[]{71,72,22}, grid.rows().get(1).toArray());
        
        grid.column("x").set(4, 73);
        grid.column("y").set(4, 74);
        
        assertArrayEquals(new Object[]{73,74,52}, grid.rows().get(4).toArray());
    }
    
    @Test
    public void testSort() {
        Grid expected1 = new Grid()
            .header("n", "time", "dt")
            .add(1, 20, 0)
            .add(2, 40, 0)
            .add(4, 15, 1)
            .add(5, 15, 1)
            .add(0, 30, 1)
            .add(3, 50, 2);
        Grid expected2 = new Grid()
            .header("n", "time", "dt")
            .add(0, 30, 1)
            .add(1, 20, 0)
            .add(2, 40, 0)
            .add(3, 50, 2)
            .add(4, 15, 1)
            .add(5, 15, 1);
        Grid expected3 = new Grid()
            .header("n", "time", "dt")
            .add(4, 15, 1)
            .add(5, 15, 1)
            .add(1, 20, 0)
            .add(0, 30, 1)
            .add(2, 40, 0)
            .add(3, 50, 2);
        
        Grid<Integer> grid = new Grid<>()
            .header("n", "time", "dt")
            .add(0, 30, 1)
            .add(1, 20, 0)
            .add(2, 40, 0)
            .add(3, 50, 2)
            .add(4, 15, 1)
            .add(5, 15, 1);
        
        grid.sort("dt", "time", "n");
        assertEquals(expected1, grid);
        assertFalse(expected2.equals(grid));
        assertFalse(expected3.equals(grid));
        
        grid.sort("n");
        assertFalse(expected1.equals(grid));
        assertFalse(expected3.equals(grid));
        assertEquals(expected2, grid);
        
        grid.sort("time", "n", "dt");
        assertFalse(expected1.equals(grid));
        assertFalse(expected2.equals(grid));
        assertEquals(expected3, grid);
    }
}
