/* CST8110 - Introduction to Computer Programming
 * Section: 800
 * Semester: 20W
 * Professor: Piyush Jangam
 * Student ID: 040750891
 * Student Email: ross0272@algonquinlive.com
 * Practical Assessment 1
 */

import java.util.Random;
import java.util.Scanner;

public class Game {
    private String playerName; // Name of the user
    private int player; // User = 1, Computer = 2

    private Scanner input; // For getting input from the user
    private Random rand; // Random number generator

    // Various file types for the game
    private File pdf;
    private File docx;
    private File xlsx;
    private File java;
    // invalidChoice is used to avoid null pointer exceptions and is always 0
    private File invalidChoice;

    public Game() {
        //Initialize input, rand, and player variables to starting values
        input = new Scanner(System.in);
        rand = new Random();
        player = 1;

        //Get playerName from the user
        System.out.print("Please enter your name: ");
        playerName = input.nextLine();

        //Get a random odd number between 3 and 9 inclusive
        int starterValue = initializeRandomValue();
        //Use that number to initialize the pdf, docx, xlsx, and java Files
        pdf = new File(starterValue);
        docx = new File(starterValue + 2);
        xlsx = new File(starterValue + 4);
        java = new File(starterValue + 6);

        //Used to avoid a null pointer exception later on, invalidChoice should always be empty
        invalidChoice = new File(0);

        //Display intro text
        System.out.println("Welcome to the Game!\n"
            + "You'll need to first pick a file type,\n"
            + "then select how many files you wish to remove.\n");
    }

    /* Separating this out into its own method.
     * Logic is different and distinct from constructor logic
     */
    private int initializeRandomValue() {
        // Create a random value between 3 and 9 inclusive
        int rValue = rand.nextInt(6)+ 3;
        // If the number is even, add 1 to make it odd
        if (rValue % 2 == 0) {
            rValue++;
        }
        return rValue;
    }

    // Displays the current stats for the game
    private void displayGame(){
        System.out.println("  PDF | DOCX | XLSX | JAVA ");
        System.out.printf(" %4d | %4d | %4d | %4d%n",
            pdf.getNumFiles(), docx.getNumFiles(),
            xlsx.getNumFiles(), java.getNumFiles());
    }

    // Returns which File the user chooses
    private File userChooseFile() {
        // Initialize userChoice to an empty File to avoid null pointer exceptions
        File userChoice = invalidChoice;
        // Repeat the following block until a non-empty File is chosen
        do {
            // Display instructions for user and get input
            System.out.printf("%s, select a file type:%n", playerName);
            System.out.print("Press 1 for PDF, 2 for DOCX, 3 for XLSX or 4 for JAVA: ");
            int selection = input.nextInt();
            /* Use the user's input to assign the appropriate File to selectedFile.
             * If the user's selection is empty, print an error message.
             * The else statements in the switch statement are redundant,
             * I included them more for readability than for functionality.
             */
            switch (selection) {
                case 1:
                    if (pdf.isEmpty()) {
                        System.out.println("PDF is already empty!");
                    }
                    else {
                        userChoice = pdf;
                    }
                    break;
                case 2:
                    if (docx.isEmpty()) {
                        System.out.println("DOCX is already empty!");
                    }
                    else {
                        userChoice = docx;
                    }
                    break;
                case 3:
                    if (xlsx.isEmpty()) {
                        System.out.println("XLSX is already empty!");
                    }
                    else {
                        userChoice = xlsx;
                    }
                    break;
                case 4:
                    if (java.isEmpty()) {
                        System.out.println("JAVA is already empty!");
                    }
                    else {
                        userChoice = java;
                    }
                    break;
                default:
                    // If the user chooses an invalid option, display an error
                    System.out.println("That's not a valid option! Try again.");
                    break;
                }
            } while (userChoice.isEmpty());
        return userChoice;
    }

    // Returns how many files the user wants to remove
    private int userChooseNum() {
        System.out.print("Enter number of files to remove: ");
        return input.nextInt();
    }

    // Returns which File the computer chooses
    private File computerChooseFile() {
        // Initialize computerChoice to an empty File to avoid null pointer exceptions
        File computerChoice = invalidChoice;
        System.out.print("Computer, select a file type: ");
        // Repeat the following block until a non-empty File is chosen
        do {
            // Generate a random number between 0 and 3, inclusive
            int randFileType = rand.nextInt(4);
            /* In order to avoid using the continue statement, and to keep my code as concise as
             * possible, I reversed the if statement for deciding whether to print the file type.
             * If the file is empty the loop will repeat anyways, so using continue is superfluous.
             */
            switch (randFileType) {
                case 0:
                    computerChoice = pdf;
                    if (!computerChoice.isEmpty()) {
                        System.out.println("PDF");
                    }
                    break;
                case 1:
                    computerChoice = docx;
                    if (!computerChoice.isEmpty()) {
                        System.out.println("DOCX");
                    }
                    break;
                case 2:
                    computerChoice = xlsx;
                    if (!computerChoice.isEmpty()) {
                        System.out.println("XLSX");
                    }
                    break;
                case 3:
                    computerChoice = java;
                    if (!computerChoice.isEmpty()) {
                        System.out.println("JAVA");
                    }
                    break;
                default:
                    /* This should never occur, but I'll leave it in anyway, using the invalidChoice
                     * as a buffer to stop null pointer exceptions
                     */
                    break;
            }
        } while(computerChoice.isEmpty());
        return computerChoice;
    }

    // Returns how many files the computer wants to remove
    private int computerChooseNum(File theFile) {
        System.out.print("Computer, choose number of files to remove: ");
        // If there's only 1 file left of the chosen type, 1 must be removed
        if (theFile.getNumFiles() == 1) {
            return 1;
        }
        // If more than 1 file remains,
        // a random number between 1 and half the remaining number is chosen
        else {
            return rand.nextInt(theFile.getNumFiles() / 2) + 1;
        }
    }

    // Creates the environment for each turn and executes the turn
    public void playGame(){
        // Display the current stats
        displayGame();
        // Initialize the selections to an empty file and 0
        File selectedFile = invalidChoice;
        int numFilesToRemove = 0;

        // Checks whether it's the user's turn and gets the user's selections
        if (player == 1) {
            selectedFile = userChooseFile();
            numFilesToRemove = userChooseNum();
        }
        // Checks whether it's the computer's turn and gets the computer's selections
        else if (player == 2) {
            selectedFile = computerChooseFile();
            numFilesToRemove = computerChooseNum(selectedFile);
            // User's input is displayed automatically, computer needs to manually display choice
            System.out.println(numFilesToRemove);
        }
        // Local variable itWorked is unnecessary, but helps readability
        boolean itWorked = selectedFile.removeFiles(numFilesToRemove);
        if (!itWorked) {
            return;
        }
        // Toggle the current player
        if (player == 1) {
            player = 2;
        }
        else {
            player = 1;
        }
    }

    // Determines if the game has been won, and if so by which player
    public int determineWinner() {
        // Initialize winner to 0, meaning not a valid player
        int winner = 0;
        // Find the total of all remaining Files
        int allFiles = pdf.getNumFiles() + docx.getNumFiles()
            + xlsx.getNumFiles() + java.getNumFiles();
        // If there are no files left, the winner is the current player
        if (allFiles == 0) {
            winner = player;
            // If the winner is player 1, the user has won
            if (winner == 1) {
                System.out.println(playerName + " wins!");
            }
            // If the winner is player 2, the computer has won
            else {
                System.out.println("Computer wins!");
            }
        }
        return winner;
    }

    public static void main(String[] args) {
        Game game = new Game();
        // Repeat the turns until a valid winner is found (1 or 2)
        do {
            game.playGame();
        } while (game.determineWinner() == 0);
        System.out.println("Thanks for playing!");
    }
}
