package net.woodyfolsom.msproj.policy;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.List;

import net.woodyfolsom.msproj.Action;
import net.woodyfolsom.msproj.GameConfig;
import net.woodyfolsom.msproj.GameState;
import net.woodyfolsom.msproj.Player;

import org.junit.Test;


public class RandomTest {
	
	@Test(expected = IllegalArgumentException.class)
	public void testGenmoveForNone() {
		Policy moveGenerator = new RandomMovePolicy();
		GameConfig gameConfig = new GameConfig(5);
		GameState gameState = new GameState(gameConfig);
		moveGenerator.getAction(gameConfig, gameState, Player.BLACK);
		gameConfig = new GameConfig(5);
		gameState = new GameState(gameConfig);
		moveGenerator.getAction(gameConfig, gameState, Player.WHITE);
		
		assertEquals(Action.PASS, moveGenerator.getAction(gameConfig, gameState, Player.NONE));
	}
	
	@Test
	public void testAlternativeToIllegalMove() {
		GameConfig gameConfig = new GameConfig(4);
		GameState gameState = new GameState(gameConfig);
		
		assertTrue(gameState.placeStone(Player.BLACK, Action.getInstance("A1")));
		assertTrue(gameState.placeStone(Player.BLACK, Action.getInstance("A2")));
		assertTrue(gameState.placeStone(Player.BLACK, Action.getInstance("A3")));
		assertTrue(gameState.placeStone(Player.BLACK, Action.getInstance("A4")));
		assertTrue(gameState.placeStone(Player.BLACK, Action.getInstance("B1")));
		assertTrue(gameState.placeStone(Player.BLACK, Action.getInstance("B2")));		
		assertTrue(gameState.placeStone(Player.BLACK, Action.getInstance("B4")));	
		assertTrue(gameState.placeStone(Player.BLACK, Action.getInstance("C2")));
		assertTrue(gameState.placeStone(Player.BLACK, Action.getInstance("C3")));
		assertTrue(gameState.placeStone(Player.BLACK, Action.getInstance("C4")));	
		assertTrue(gameState.placeStone(Player.BLACK, Action.getInstance("D4")));
		assertTrue(gameState.placeStone(Player.WHITE, Action.getInstance("C1")));
		assertTrue(gameState.placeStone(Player.WHITE, Action.getInstance("D2")));
		assertTrue(gameState.placeStone(Player.WHITE, Action.getInstance("D3")));
		
		assertTrue(gameState.playStone(Player.BLACK, Action.PASS));
		
		System.out.println("State before random WHITE move selection:");
		System.out.println(gameState);
		
		//This is correct - checked vs. MFOG
		//PASS would otherwise be a valid move
		List<Action> prohibitedMoves = new ArrayList<Action>();
		prohibitedMoves.add(Action.PASS);
		
		assertEquals(Action.getInstance("B3"), new RandomMovePolicy().getAction(gameConfig, gameState, prohibitedMoves, Player.WHITE));
		
		System.out.println(gameState);
	}
	
	@Test
	public void testIllegalMoveSuicide() {
		GameConfig gameConfig = new GameConfig(3);
		GameState gameState = new GameState(gameConfig);
		
		assertTrue(gameState.placeStone(Player.WHITE, Action.getInstance("A1")));
		assertTrue(gameState.placeStone(Player.WHITE, Action.getInstance("B1")));
		assertTrue(gameState.placeStone(Player.WHITE, Action.getInstance("B2")));
		assertTrue(gameState.placeStone(Player.WHITE, Action.getInstance("A3")));
		assertTrue(gameState.placeStone(Player.WHITE, Action.getInstance("B3")));
		
		System.out.println("State before move: ");
		System.out.println(gameState);
		RandomMovePolicy randomMovePolicy = new RandomMovePolicy();
		
		//There is only a minute chance (5E-7) that RandomMoveGenerator fails to return an invalid move with probability 1/4
		//after 50 calls, if this bug recurs.
		for (int i = 0; i < 50; i++) {
			Action action = randomMovePolicy.getAction(gameConfig,gameState,Player.BLACK);
			//System.out.println(action);
			assertFalse("RandomMovePolicy returned illegal suicide move A2",action.equals(Action.getInstance("A2")));
		}
	}
	
	@Test
	public void testIllegalMoveKo() {
		GameConfig gameConfig = new GameConfig(4);
		GameState gameState = new GameState(gameConfig);
		
		assertTrue(gameState.placeStone(Player.WHITE, Action.getInstance("B1")));
		assertTrue(gameState.placeStone(Player.WHITE, Action.getInstance("A2")));
		assertTrue(gameState.placeStone(Player.WHITE, Action.getInstance("C2")));
		assertTrue(gameState.placeStone(Player.WHITE, Action.getInstance("B3")));
		assertTrue(gameState.placeStone(Player.BLACK, Action.getInstance("A3")));
		assertTrue(gameState.placeStone(Player.BLACK, Action.getInstance("C3")));
		assertTrue(gameState.placeStone(Player.BLACK, Action.getInstance("B4")));
		
		System.out.println("State before move: ");
		System.out.println(gameState);
		assertTrue(gameState.playStone(Player.BLACK, Action.getInstance("B2")));
		System.out.println("State after move: ");
		System.out.println(gameState);
		
		RandomMovePolicy randomMovePolicy = new RandomMovePolicy();
		//Test that after 50 moves, the policy never returns B3, which would be a Ko violation
		for (int i = 0; i < 50; i++) {
			Action action = randomMovePolicy.getAction(gameConfig,gameState,Player.WHITE);
			//System.out.println(action);
			assertFalse(action.equals(Action.NONE));
			assertFalse("RandomMovePolicy returned Ko violation move B3",action.equals(Action.getInstance("B3")));
		}
	}
}
