package net.woodyfolsom.msproj.policy;

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

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

public class RandomMovePolicy implements Policy, ActionGenerator {
	private boolean logging = false;
	
	/**
	 * Does NOT modify the gameState.
	 */
	public Action getAction(GameConfig gameConfig, GameState gameState,
			Collection<Action> prohibitedMoves, Player player) {
		return getActions(gameConfig, gameState, prohibitedMoves, player, 1).get(0);
	}

	/**
	 * Attempts to generate up to nMoves random moves on behalf of the specified
	 * player. Will return at least one move, which may be 'NONE' if random
	 * search does not succeed in discovering a valid move. Does NOT modify the
	 * gameState.
	 * 
	 * @param gameConfig
	 * @param gameState
	 * @param color
	 * 
	 * @return
	 */
	public List<Action> getActions(GameConfig gameConfig, GameState gameState,
			Collection<Action> prohibitedMoves, Player player, int nMoves) {
		List<Action> randomActions = new ArrayList<Action>();
		
		if (player != gameState.getPlayerToMove()) {
			throw new IllegalArgumentException("It is not " + player
					+ "'s turn to move!");
		}

		GameState gameStateCopy = new GameState(gameState);
		ActionGenerator actionGenerator = new ValidMoveGenerator();

		List<Action> possibleActions = actionGenerator.getActions(gameConfig,
				gameStateCopy, prohibitedMoves, player,
				ActionGenerator.ALL_ACTIONS);

		boolean playerIsWinning = gameState.getResult().isWinner(player);
		
		while (possibleActions.size() > 0 && randomActions.size() < nMoves) {
			Action randomAction = possibleActions
					.remove((int) (Math.random() * possibleActions.size()));

			if (isValidRandomAction(randomAction, player,playerIsWinning, gameState)) {
				randomActions.add(randomAction);
			}
		}
		
		//PASS is always the move of last resort if no valid moves exist
		//Action.NONE exists for a reason - if the fail-safe was to ALWAYS return PASS, then MCTS would
	    //fail to descend properly because the root node would always appear to have additional unexplored actions.
		if (randomActions.size() == 0) {
			if (prohibitedMoves.contains(Action.PASS)) {
				randomActions.add(Action.NONE);
			} else {
				randomActions.add(Action.PASS);
			}
		}
		
		//when to resign?

		return randomActions;
	}

	private boolean isValidRandomAction(Action action, Player player, boolean playerIsWinning, GameState gameState) {
		//do not pass while losing
		if (action.isPass()) {
			return playerIsWinning;
		}
		//do not fill in my own eye
		return !gameState.isSelfFill(action, player);
	}
	/**
	 * RandomMoveGenerator does not evaluate any states, but simply returns
	 * elements of a set of uniformly distributed, distinct valid moves.
	 * 
	 * @return
	 */
	public int getNumStateEvaluations() {
		return 0;
	}

	@Override
	public List<Action> getActions(GameConfig gameConfig, GameState gameState,
			Player color, int numActions) {
		return getActions(gameConfig, gameState, new ArrayList<Action>(),
				color, numActions);
	}

	@Override
	public Action getAction(GameConfig gameConfig, GameState gameState,
			Player player) {
		Action randomAction = getActions(gameConfig, gameState, player, 1).get(0);
		if (logging) {
			System.out.println("Random action " + randomAction + " selected for " + player + ".");
		}
		return randomAction;
	}

	public boolean isLogging() {
		return logging;
	}
	
	public void setLogging(boolean isLogging) {
		this.logging = isLogging;
	}
	
	@Override
	public void setState(GameState gameState) {
		// TODO Auto-generated method stub	
	}
}