import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;

public class Mastermind {
    /**
     * Class to represent a Mastermind game.
     * Mastermind is a game where the player has to guess a secret code consisting of 4 numbers between 1 and 6.
     * The player has 10 chances to guess the code and wins if he can guess the code within 10 chances.
     * Each time the player makes a guess, the game will return a tuple of 2 numbers between 0 and 4.
     * The hints are as follows:
     * - The first digit indicates the number of correct numbers in the correct position
     * - The second digit indicates the number of correct numbers in the wrong position
     * Note: If there are duplicate colors in the guess, they cannot all get a hint unless
     * they correspond to the same number of duplicate colors in the hidden code.
     */

    private final int nbDigits;
    private final int nbColors;
    private List<Integer> code;
    private int chances;

    /**
     * Initialize the Mastermind game with a secret code.
     *
     * @param chances  the number of chances the player has to guess the code. Default is 10.
     * @param nbDigits the number of digits in the code. Default is 4.
     * @param nbColors the number of colors (or digits) that can be used in the code. Default is 6.
     */
    public Mastermind(int chances, int nbDigits, int nbColors) {
        this.nbDigits = nbDigits;
        this.nbColors = nbColors;
        this.chances = chances;
        this.code = generateCode();
    }

    /**
     * Default constructor initializing the game with default values.
     */
    public Mastermind() {
        this(10, 4, 6);
    }

    /**
     * Generate a random code.
     *
     * @return a list of integers representing the secret code.
     */
    private List<Integer> generateCode() {
        Random random = new Random();
        List<Integer> code = new ArrayList<>();
        for (int i = 0; i < nbDigits; i++) {
            code.add(random.nextInt(nbColors) + 1);
        }
        return code;
    }

    /**
     * Set the secret code. This method is useful for testing purposes.
     * It calls the checkCode method to validate the code.
     *
     * @param code the secret code
     * @throws IllegalArgumentException if the code is invalid
     */
    public void setCode(List<Integer> code) {
        if (checkCode(code)) {
            this.code = code;
        } else {
            throw new IllegalArgumentException(
                    "Invalid code. Please enter " + nbDigits + " numbers between 1 and " + nbColors + ".");
        }
    }

    /**
     * Check if the code is valid.
     *
     * @param code the code to be checked
     * @return true if the code is valid, false otherwise
     */
    public boolean checkCode(List<Integer> code) {
        return true;
    }

    /**
     * Each time the player makes a guess, the game will return a couple of numbers between 0 and 4.
     * The hints are as follows:
     * - The first digit indicates the number of correct numbers in the correct position
     * - The second digit indicates the number of correct numbers in the wrong position
     * Note: If there are duplicate colors in the guess, they cannot all get a hint unless
     * they correspond to the same number of duplicate colors in the hidden code.
     *
     * @param code  the secret code
     * @param guess the player's guess
     * @return an array of two integers representing the hints
     */
    public static int[] provideHints(List<Integer> code, List<Integer> guess) {
        return new int[]{2, 0};
    }

    /**
     * Check if the player has remaining attempts.
     *
     * @return true if the player has remaining attempts, false otherwise
     */
    public boolean hasRemainingAttempts() {
        return true;
    }

    /**
     * Check if the guess is the right answer.
     * Instead of checking the guess, the hints are provided as input.
     *
     * @param hints the hints provided after making a guess
     * @return true if the hints are (4,0), false otherwise
     */
    public boolean isRightAnswer(int[] hints) {
        return true;
    }

    /**
     * Make a guess and return the hints.
     *
     * @param guess the guess
     * @return an array of three integers: first element indicates if the guess is correct (1 if true, 0 if false),
     * the second element indicates the number of correct numbers in the correct position,
     * the third element indicates the number of correct numbers in the wrong position.
     */
    public int[] guess(List<Integer> guess) {
        if (!hasRemainingAttempts()) {
            System.out.println("Game over! You have run out of chances.");
            return new int[]{0, 0, 0};
        }
        if (!checkCode(guess)) {
            System.out.println("Invalid guess. Please enter " + nbDigits + " numbers between 1 and " + nbColors + ".");
            return new int[]{0, 0, 0};
        }
        chances--;
        int[] hints = provideHints(code, guess);
        boolean success = isRightAnswer(hints);
        return new int[]{success ? 1 : 0, hints[0], hints[1]};
    }

    /**
     * Convert a string to a list of integers.
     * In the string, each integer is separated by a space.
     *
     * @param word the string to be converted
     * @return a list of integers
     * @throws IllegalArgumentException if the input is invalid
     */
    public static List<Integer> convert(String word) {
        String[] parts = word.split(" ");
        List<Integer> numbers = new ArrayList<>();
        try {
            for (String part : parts) {
                numbers.add(Integer.parseInt(part));
            }
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("Invalid input: "+ word +". Please enter numbers separated by spaces.");
        }
        return numbers;
    }

    public static void main(String[] args) {
        Mastermind game = new Mastermind();
        Scanner scanner = new Scanner(System.in);

        // Print a welcome message and instructions
        System.out.println("Welcome to Mastermind!");
        System.out.println("You have " + game.chances + " chances to guess the secret code.");
        System.out.println("The code consists of " + game.nbDigits + " numbers between 1 and " + game.nbColors + ".");
        System.out.println("After each guess, you will receive hints:");
        System.out.println("- The first digit indicates the number of correct numbers in the correct position.");
        System.out.println("- The second digit indicates the number of correct numbers in the wrong position.");
        System.out.println("Enter your guess as a sequence of numbers separated by spaces.\n");
        System.out.println("Let's start!");

        // Read the guess from the player
        while (game.hasRemainingAttempts()) {
            System.out.print("Please enter your guess: ");
            String userGuess = scanner.nextLine();

            // Convert the guess to a list of integers
            List<Integer> guessList = convert(userGuess);

            // Call the guess method and print the hints
            int[] result = game.guess(guessList);
            if (result[0] == 1) {
                System.out.println("Congratulations! You have guessed the code.");
                break;
            } else {
                System.out.println("Hints: (" + result[1] + ", " + result[2] + ")");
                System.out.println("You have " + game.chances + " chances left.");
            }
        }

        if (!game.hasRemainingAttempts()) {
            System.out.println("Game over! You have run out of chances.");
            System.out.println("The secret code was: " + game.code);
        }

        scanner.close();
    }
}