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

import org.junit.jupiter.api.Test;

public class FourTest
{
    private static Candy[][] getShallowCopy(Candy[][] box)
    {
        Candy[][] shallowCopy = new Candy[box.length][box[0].length];
        
        for(int r = 0; r < shallowCopy.length; r++)
            for(int c = 0; c < shallowCopy[0].length; c++)
                shallowCopy[r][c] = box[r][c];
        
        return shallowCopy;
    }
    
    // references must be to exact same objects
    public static boolean equals(Candy[][] one, Candy[][] two)
    {
        if(one.length != two.length || one[0].length != two[0].length)
            return false;
        
        for(int r = 0; r < one.length; r++)
            for(int c = 0; c < one[0].length; c++)
                if(one[r][c] != two[r][c])
                    return false;
        
        return true;
    }
    
    @Test
    public void testMoveCandyToFirstRow()
    {
        BoxOfCandy boc = new BoxOfCandy();
        boc.box = new Candy[4][3];
        boc.box[0][1] = new Candy("lime");
        boc.box[1][1] = new Candy("orange");
        boc.box[2][2] = new Candy("cherry");
        boc.box[3][1] = new Candy("lemon");
        boc.box[3][2] = new Candy("grape");
        
        Candy[][] expectedResult = getShallowCopy(boc.box);
        
        assertTrue( ! boc.moveCandyToFirstRow(0) );
        assertTrue(equals(expectedResult, boc.box));
        
        assertTrue(boc.moveCandyToFirstRow(1));
        assertTrue(equals(expectedResult, boc.box));
        
        Candy[][] expectedResultAlt = getShallowCopy(expectedResult);
        
        expectedResult[0][2] = expectedResult[2][2];
        expectedResult[2][2] = null;
        
        expectedResultAlt[0][2] = expectedResultAlt[3][2];
        expectedResultAlt[3][2] = null;
        
        assertTrue(boc.moveCandyToFirstRow(2));
        assertTrue(
                equals(expectedResult, boc.box) ||
                equals(expectedResultAlt, boc.box));
    }
    
    @Test
    public void testRemoveNextFlavor()
    {
        BoxOfCandy boc = new BoxOfCandy();
        boc.box = new Candy[3][5];
        boc.box[0][0] = new Candy("lime");
        boc.box[0][1] = new Candy("lime");
        boc.box[0][3] = new Candy("lemon");
        boc.box[1][0] = new Candy("orange");
        boc.box[1][3] = new Candy("lime");
        boc.box[1][4] = new Candy("lime");
        boc.box[2][0] = new Candy("cherry");
        boc.box[2][2] = new Candy("lemon");
        boc.box[2][4] = new Candy("orange");
        
        Candy[][] expectedBox = getShallowCopy(boc.box);
        Candy expectedResult = expectedBox[2][0];
        expectedBox[2][0] = null;
        
        assertTrue(boc.removeNextByFlavor("cherry") == expectedResult); // == intentional
        assertTrue(equals(expectedBox, boc.box));
        
        expectedResult = expectedBox[1][3];
        expectedBox[1][3] = null;
        
        assertTrue(boc.removeNextByFlavor("lime") == expectedResult);
        assertTrue(equals(expectedBox, boc.box));
        
        expectedResult = null;
        
        assertTrue(boc.removeNextByFlavor("grape") == expectedResult);
        assertTrue(equals(expectedBox, boc.box));
    }
}
