/**
 * BattleshipGame.java
 *
 *
 * Caitlin Ross
 *  
 * 100735219
 */

import java.util.*;

public class BattleshipGame {
	
	private Board[] boards;
	private int boardSize = 10;
	private Boat[] boats;
	private final int numberOfShips = 4, user = 0, enemy = 1;
	private int lastEnemyHitRow, lastEnemyHitColumn;
	private String playerName, computerName;
	
    public BattleshipGame(String aPlayerName, String aComputerName) {
    	boards = new Board[2];
    	boards[user] = new Board(boardSize);
    	boards[enemy] = new Board(boardSize);
    	playerName = aPlayerName;
    	computerName = aComputerName;
    }
    
    public Board getBoard(int whichBoard){return boards[whichBoard];}
    public int userNum(){return user;}
    public int enemyNum(){return enemy;}
    
    public void placeUserShips(){
    	boats = new Boat[4];
    	String location;
    	int rCoordinate, cCoordinate;		//r for row, c for column
    	char direction;
    	
    	for(int i=0; i<numberOfShips; i++){
        	boats[i] = new Boat(i, this);
        	
        	displayBoards();
        	
        	do{
        		try{
        			System.out.print("\nEnter " + boats[i].getName() + " location and direction (e.g. 2,2,h): ");
        			location = new Scanner(System.in).nextLine();
        			if (i==0 && location.equals("*")){
        				placeRandomShips(user);
        				i=numberOfShips; // to break out of for-loop
        				break;
        			}
        			
        			StringTokenizer aTokenizer = new StringTokenizer(location, ", ");
        			rCoordinate = Integer.parseInt(aTokenizer.nextToken());
        			cCoordinate = Integer.parseInt(aTokenizer.nextToken());
        			direction = aTokenizer.nextToken().charAt(0);
        		}
        		catch(java.util.NoSuchElementException e){
        			System.out.println("That's not a valid ship position! Use the format 4,3,h");
        			i--;	//to stay in same place in the for loop
        			break;
        		}
        		catch(java.lang.NumberFormatException e){
        			System.out.println("That's not a valid ship position! Use integers.");
        			i--;	//to stay in same place in the for loop
        			break;
        		}
        		
        		if (!boats[i].checkLocation(rCoordinate, cCoordinate, direction, user))
        			System.out.print("\n\tThat's not a valid ship position! A " + boats[i].getName() + " won't fit there.");
        		else{
        			boats[i].setLocation(rCoordinate, cCoordinate, direction, user);
        			break;
        		}
        	
        	}while(!boats[i].checkLocation(rCoordinate, cCoordinate, direction, user));	
        }
    }
    
    public void placeRandomShips(int whichPlayer){
    	int rCoordinate, cCoordinate, chooseDirection;
    	char direction;
    	
    	for(int i=0; i<numberOfShips; i++){
    		boats[i] = new Boat(i, this);
    		
    		do{
    			rCoordinate = (int)(Math.random()*100)%boardSize;
    			cCoordinate = (int)(Math.random()*100)%boardSize;
    			chooseDirection = (int)(Math.random()*10)%2; //only 2 choices: horizontal or vertical
    			
    			if (chooseDirection == 0)
    				direction = 'h';
    			else
    				direction = 'v';
    			
    			if (boats[i].checkLocation(rCoordinate, cCoordinate, direction, whichPlayer)){
    				boats[i].setLocation(rCoordinate, cCoordinate, direction, whichPlayer);
    				break;
    			}
    			
    		}while (!boats[i].checkLocation(rCoordinate, cCoordinate, direction, whichPlayer));
    	}
    }
    
    public void displayBoards(){
    	System.out.println("\n\n=====================================================\n");
    	System.out.print('\t' + playerName + '\t');
    	if (playerName.length()<20)
    		System.out.print('\t');
    	if (playerName.length()<16)
    		System.out.print('\t');
    	if (playerName.length()<12)
    		System.out.print('\t');
    	if (playerName.length()<8)
    		System.out.print('\t');
    	if (playerName.length()<4)
    		System.out.print('\t');
    	System.out.println(computerName);
    	
    	for(int i=0; i<2; i++){		//2 for the 2 players
    		System.out.print("\t  ");
    		for (int j=0; j<boardSize; j++){
    			System.out.print(j + " ");
    		}
    	}
    	
    	System.out.println("");
    	
    	for (int i=0; i<boardSize; i++){
    		System.out.print('\t');
    		boards[user].displayRow(i, user);
    		System.out.print('\t');
    		boards[enemy].displayRow(i, enemy);
    		System.out.println("");
    	}
    }
    
    public boolean hasPlayerWon(int player){
    	for(int i=0; i<numberOfShips; i++){
    		if(!boats[i].isBoatSunk(player))
    			return false;
    	}
    	return true;
    }
    
    public void move(int moveNumber){
    	String playerMove;
    	int rCoordinate = -2;
    	int cCoordinate = -2;
    	int notPlayer;
    	int player = moveNumber%2;
    	
    	if (player == user){
    		displayBoards();
    		notPlayer = enemy;
    	}
    	else
    		notPlayer = user;
    	
    	do{
    		if (player == user){
    			boolean exceptionFound = false;
    			try{
        			System.out.print("\nEnter your move, " + playerName + " (in the format row,column e.g. 4,3): ");
    				playerMove = new Scanner(System.in).nextLine();
        					
        			StringTokenizer aTokenizer = new StringTokenizer(playerMove, ", ");
        			rCoordinate = Integer.parseInt(aTokenizer.nextToken());
        			cCoordinate = Integer.parseInt(aTokenizer.nextToken());
        		}
       			catch(java.util.NoSuchElementException e){
        			System.out.println("Sorry, that's not a valid move. Use the format 4,3");
        			exceptionFound = true;
        		}
        		catch(java.lang.NumberFormatException e){
        			System.out.println("Sorry, that's not a valid move. Use integers.");
        			exceptionFound = true;
        		}
        		if (rCoordinate == -1 && cCoordinate == -1){
        			cheat();
        		}
        		else if(!boards[enemy].isValidMove(rCoordinate, cCoordinate) && exceptionFound == false)
        			System.out.println("Sorry, that's not a valid move. Choose integers between 0 and 9, and make sure you haven't already hit that piece.");
        		if (boards[enemy].isValidMove(rCoordinate, cCoordinate)){
        			boards[enemy].hitPiece(rCoordinate, cCoordinate);
        			if(boards[enemy].getPiece(rCoordinate, cCoordinate) == '~'){
        				System.out.println('\n' + playerName + ", you missed!");
        			}
        			else{
        				System.out.println('\n' + playerName + ", you hit a ship!");
        				for(int i=0; i<numberOfShips; i++){
        					if (boats[i].isBoatSunk(enemy)){
        						boats[i].sinkShip();
        					}
        				}
        			}
        			break;
        		}
    		}
    		else if (player == enemy){
    			if (lastEnemyHitRow == -1 || lastEnemyHitColumn == -1){
    				rCoordinate = (int)(Math.random()*100)%boardSize;
    				cCoordinate = (int)(Math.random()*100)%boardSize;
    			}
    			else{
    				if (lastEnemyHitRow+1<boardSize && boards[user].getPiece(lastEnemyHitRow+1, lastEnemyHitColumn) != '~'
    				 && boards[user].isPieceHit(lastEnemyHitRow+1, lastEnemyHitColumn) && 
    				 boards[user].isValidMove(lastEnemyHitRow - 1, lastEnemyHitColumn)){
    					rCoordinate = lastEnemyHitRow - 1;
    					cCoordinate = lastEnemyHitColumn;
    				}
    				else if (lastEnemyHitRow-1>-1 && boards[user].getPiece(lastEnemyHitRow-1, lastEnemyHitColumn) != '~'
    				 && boards[user].isPieceHit(lastEnemyHitRow-1, lastEnemyHitColumn) &&
    				 boards[user].isValidMove(lastEnemyHitRow + 1, lastEnemyHitColumn)){
    					rCoordinate = lastEnemyHitRow + 1;
    					cCoordinate = lastEnemyHitColumn;
    				}
    				else if (lastEnemyHitColumn+1<boardSize && boards[user].getPiece(lastEnemyHitRow, lastEnemyHitColumn+1) != '~'
    				 && boards[user].isPieceHit(lastEnemyHitRow, lastEnemyHitColumn+1) && 
    				 boards[user].isValidMove(lastEnemyHitRow, lastEnemyHitColumn - 1)){
    					rCoordinate = lastEnemyHitRow;
    					cCoordinate = lastEnemyHitColumn - 1;
    				}
    				else if (lastEnemyHitColumn-1>-1 && boards[user].getPiece(lastEnemyHitRow, lastEnemyHitColumn-1) != '~'
    				 && boards[user].isPieceHit(lastEnemyHitRow, lastEnemyHitColumn-1) &&
    				 boards[user].isValidMove(lastEnemyHitRow, lastEnemyHitColumn + 1)){
    					rCoordinate = lastEnemyHitRow;
    					cCoordinate = lastEnemyHitColumn + 1;
    				}
    				else if (boards[user].isValidMove(lastEnemyHitRow + 1, lastEnemyHitColumn)){
    					rCoordinate = lastEnemyHitRow + 1;
    					cCoordinate = lastEnemyHitColumn;
    				}
    				else if (boards[user].isValidMove(lastEnemyHitRow - 1, lastEnemyHitColumn)){
    					rCoordinate = lastEnemyHitRow - 1;
    					cCoordinate = lastEnemyHitColumn;
    				}
    				else if (boards[user].isValidMove(lastEnemyHitRow, lastEnemyHitColumn + 1)){
    					rCoordinate = lastEnemyHitRow;
    					cCoordinate = lastEnemyHitColumn + 1;
    				}
    				else if (boards[user].isValidMove(lastEnemyHitRow, lastEnemyHitColumn - 1)){
    					rCoordinate = lastEnemyHitRow;
    					cCoordinate = lastEnemyHitColumn - 1;
    				}
    				else{
    					rCoordinate = (int)(Math.random()*100)%boardSize;
    					cCoordinate = (int)(Math.random()*100)%boardSize;
    				}
    			}
    			
    			if (boards[user].isValidMove(rCoordinate, cCoordinate)){
    				boards[user].hitPiece(rCoordinate, cCoordinate);
    				System.out.print('\n' + computerName + " fires at " + rCoordinate + "," + cCoordinate + " and ");
    				if (boards[user].getPiece(rCoordinate, cCoordinate) == '~'){
    					System.out.println("misses");
    				}
    					
    				else{
    					System.out.println("hits");
    					if (!boards[user].isPieceSunk(rCoordinate, cCoordinate)){
    						lastEnemyHitRow = rCoordinate;
    						lastEnemyHitColumn = cCoordinate;
    					}
    					else{
    						lastEnemyHitRow = -1;
    						lastEnemyHitColumn = -1;
    					}
    				}
    					
    				break;
    			}
    		}
    	}while(!boards[notPlayer].isValidMove(rCoordinate, cCoordinate));
    }
    
    private void cheat(){
    	System.out.println("\n\n=====================================================\n");
    	System.out.print('\t' + playerName + '\t');
    	if (playerName.length()<20)
    		System.out.print('\t');
    	if (playerName.length()<16)
    		System.out.print('\t');
    	if (playerName.length()<12)
    		System.out.print('\t');
    	if (playerName.length()<8)
    		System.out.print('\t');
    	if (playerName.length()<4)
    		System.out.print('\t');
    	System.out.println(computerName);
    	
    	for(int i=0; i<2; i++){		//2 for the 2 players
    		System.out.print("\t  ");
    		for (int j=0; j<boardSize; j++){
    			System.out.print(j + " ");
    		}
    	}
    	
    	System.out.println("");
    	
    	for (int i=0; i<boardSize; i++){
    		System.out.print('\t');
    		boards[user].displayRow(i, user);
    		System.out.print('\t');
    		boards[enemy].displayCheatRow(i, enemy);
    		System.out.println("");
    	}
    }
    
}