package net.woodyfolsom.msproj;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class GameRecord {
	public enum RULES { JAPANESE, CHINESE }
	
	private GoPlayer playerBlack;
	private GoPlayer playerWhite;
	//private int numTurns = 0;
	private List<Action> moves = new ArrayList<Action>();
	private List<GameState> gameStates = new ArrayList<GameState>();
	private Map<Integer, List<String>> comments = new HashMap<Integer,List<String>>();
	private RULES rules = RULES.CHINESE;

	public GameRecord(GameConfig gameConfig) {
		gameStates.add(new GameState(gameConfig));
		//initial 'move' of Action.NONE allows for a game that starts with a board setup
		moves.add(Action.NONE);
	}
	
	/**
	 * Adds a comment for the current turn.
	 * @param comment
	 */
	public void addComment(String comment) {
		if (comments.containsKey(getNumTurns())) {
			comments.get(getNumTurns()).add(comment);
		} else {
			List<String> newComments = new ArrayList<String>();
			newComments.add(comment);
			comments.put(getNumTurns(),newComments);
		}
	}
	
	public List<String> getComments(Integer turn) {
		if (comments.containsKey(turn)) {
			return Collections.unmodifiableList(comments.get(turn));
		} else {
			return new ArrayList<String>(0);
		}
	}
	
	public GameConfig getGameConfig() {
		return gameStates.get(0).getGameConfig();
	}
	
	public GameState getGameState(Integer turn) {
		return gameStates.get(turn);
	}
	
	public Action getMove(int turn) {
		return moves.get(turn);
	}
	
	public int getNumTurns() {
		return gameStates.size() - 1;
	}

	public Player getPlayerToMove(int turn) {
		return gameStates.get(turn).getPlayerToMove();
	}
	
	public Player getPlayerToMove() {
		return gameStates.get(getNumTurns()).getPlayerToMove();
	}
	
	public GameResult getResult() {
		return gameStates.get(getNumTurns()).getResult();
	}
	
	public RULES getRules() {
		return rules;
	}
	
	public boolean isFinished() {
		return gameStates.get(getNumTurns()).isTerminal();
	}
	
	public boolean play(Player player, Action action) {
		if (isFinished()) {
			System.out.println("Unable to play " + action + " as " + player + " because the game is finished.");
			return false; //cannot make any more moves, game is over
		}
		
		GameState nextState = new GameState(gameStates.get(getNumTurns()));
		if (nextState.playStone(player, action)) {
			gameStates.add(nextState);
			moves.add(action);
			return true;
		} else {
			//TODO allow relay of an SGF to force making an invalid move?
			//It may be possible historically for a mistake to have been made,
			//and recorded.
			System.out.println("Invalid move" + " by " + player + ": " + action);
			return false; //invalid move for this player at this time
		}
	}
	
	public void setPlayer(Player player, String name, String country, String rank) {
		if (player == Player.BLACK) {
			playerBlack = new GoPlayer();
			playerBlack.setName(name);
			playerBlack.setRank(rank);
			playerBlack.setCountry(country);
		} else if (player == Player.WHITE) {
			playerWhite = new GoPlayer();
			playerWhite.setName(name);
			playerWhite.setRank(rank);
		} else {
			throw new RuntimeException("Invalid color: " + player);
		}
	}
}