/*
    Owen Sullivan
 */

package cpsc2150.extendedConnectX;

import cpsc2150.extendedConnectX.models.*;
import java.util.*;

/**
 * Class that contains the main method for running the ExtendedConnectX game, as well as
 * methods to start the game, clear the board, manipulate the current turn, play tokens, and
 * decide whether to play again (among others).
 *
 * @author Owen Sullivan
 * @version 1.0
 *
 * @invariant
 *      currentTurn = 'X' OR currentTurn = 'O'
 */
public class GameScreen {

    private static char currentTurn;
    private static IGameBoard board;

    /**
     * Main function that runs the ExtendedConnectX game.
     *
     * @param args Arguments passed from command-line
     */
    public static void main(String[] args) {

        // Create Scanner object for getting user input
        Scanner input = new Scanner(System.in);

        // Assume we're playing again (to ensure the loop runs at least once)
        char playAgain = 'Y';
        // Loop while playAgain is Y (upper or lower case)
        while (playAgain == 'Y' || playAgain == 'y') {

            // Call helper function startGame to initialize
            startGame();
            // Print the empty board
            System.out.println(board.toString());

            // Get the column the user wants to play a token in by calling helper function inputColumn
            int column = inputColumn(input);
            // While true (loops until a break statement, which will always be triggered)
            while (true) {

                // Check to make sure the column has room
                while (!board.checkIfFree(column)) {

                    // If not, prompt again (validating input)
                    System.out.println("Column is full");
                    column = inputColumn(input);

                }

                // Place token in user-specified column
                board.placeToken(currentTurn, column);

                // Print the board with the new token placed
                System.out.println(board.toString());

                // If the latest token placed results in a win, print the winner and break the inner loop
                if (board.checkForWin(column)) {

                    System.out.println("Player " + currentTurn + " Won!");
                    break;

                    // If the latest token placed results in a tie, print a tie message and break the inner loop
                } else if (board.checkTie()) {

                    System.out.println("It's a tie!");
                    break;

                }

                // Call helper function nextTurn to advance the turn
                nextTurn();
                // Get the next column to place a token in from the user by calling helper function inputColumn
                column = inputColumn(input);

            }

            // Call helper function inputPlayAgain to prompt the user to play again
            playAgain = inputPlayAgain(input);

        }

    }

    /**
     * Starts the ExtendedConnectX game.
     *
     * @post
     *      currentTurn = 'X' AND board = [ newly initialized GameBoard object ]
     */
    private static void startGame() {

        // Set currentTurn to X for initial run
        currentTurn = 'X';
        // Create new game board
        board = new GameBoard();

    }

    /**
     * Advances the game by switching the character representing whose turn it currently is to
     * the opposite of the current value.
     *
     * @post
     *      currentTurn = 'X' iff (#currentTurn = 'O') AND
     *      currentTurn = 'O' iff (#currentTurn = 'X') AND
     *      board = #board
     */
    private static void nextTurn() {

        if (currentTurn == 'X') {

            currentTurn = 'O';

        } else {

            currentTurn = 'X';

        }

    }

    /**
     * Prompts the user for input for what column to place a token in, then returns that column number.
     *
     * @param input Scanner object used for getting user input
     * @return Column number entered by the user
     *
     * @pre
     *      [ input must be initialized as a Scanner object ] AND [ input must not be closed ]
     *
     * @post
     *      inputColumn = [ integer from user input ] AND
     *      currentTurn = #currentTurn AND board = #board
     */
    private static int inputColumn(Scanner input) {

        // Prompt user for a column number and take in next integer
        System.out.println("Player "+ currentTurn + ", what column do you want to place your marker in?");
        int column = Integer.parseInt(input.nextLine());

        // Validate user input
        while (column < 0 || column > board.getNumColumns() - 1) {

            // If column is too low, print error
            if (column < 0) {

                System.out.println("Column cannot be less than 0");

                // If column is too high, print error
            } else {

                System.out.println("Column cannot be greater than " + (board.getNumColumns() - 1));

            }

            System.out.println("Player "+ currentTurn + ", what column do you want to place your marker in?");
            column = Integer.parseInt(input.nextLine());

        }

        return column;

    }

    /**
     * Prompts the user for input for whether to play again, then returns the input.
     *
     * @param input Scanner object used for getting user input
     * @return Character option entered by the user
     *
     * @pre
     *      [ input must be initialized as a Scanner object ] AND [ input must not be closed ]
     *
     * @post
     *      inputPlayAgain = [ character from user input ] AND
     *      currentTurn = #currentTurn AND board = #board
     */
    private static char inputPlayAgain(Scanner input) {

        // Prompt user to play again and take in char input
        System.out.println("Would you like to play again? Y/N");
        char playAgain = input.nextLine().charAt(0);

        // Validate user input
        while (playAgain != 'Y' && playAgain != 'y' && playAgain != 'N' && playAgain != 'n') {

            System.out.println("Would you like to play again? Y/N");
            playAgain = input.nextLine().charAt(0);

        }

        return playAgain;

    }

}
