import java.io.IOException;
import java.util.ArrayList;
import java.lang.Math;

/**
 * The Tournament2_0 class contains code to read lines of 
 * (participant name, integer ranking) pairs from a file, create a list of
 * partipants ordered by ranking, and generate a bracket of matchups
 * for the tournament (including a starting "bye round" if one is needed).
 * 
 * @author Alyce Brady
 * @version 28 December 2025
 */
public class Tournament2_0
{
    private int numRounds;      // # of rounds in the tournament
    private int numByes;        // # of participants with byes in first round
    private BracketTree bracket;    // the bracket; contains all matchups

    /** Constructs an object that represents a tournament of players.
     */
    public Tournament2_0()
    {
        this.numRounds = 0;
        this.numByes = 0;
        this.bracket = new BracketTree();  // will actually be set by
                                           // generateBracket
    }

    /** Runs a simulated tournament, asking the user for files containing
     *  rankings and scores, identifying initial matchups and byes, and
     *  showing matchups and then scores for each round.
     *      @throw java.io.IOException if there are errors reading files
     */
    public void runTournament() throws java.io.IOException
    {
        // Read in the rankings and print them.
        K_SimpleList<ParticipantInfo> rankings = getRankings();

        // Determine how many rounds we'll need, and whether there are
        // any byes.
        setRoundsAndByes(rankings);

        // Create the bracket tree for the tournament.
        generateBracket(rankings);

        // If there is a bye round, call that Round 0. Otherwise start with
        // Round 1.
        int roundNum = 0;
        String roundName;
        if ( this.numByes != 0 )        // if there are byes...
            roundName = "Bye Round (Round 0)";
        else                            // no need for a bye round...
        {
            roundNum++;             // Start with Round 1 if no byes
            this.numRounds++;       // ... and increment final round number
            roundName = "Round " + roundNum;
        }

/* TEMPORARY CODE to simulate play for just 1 round (Round 0 or 1). */
simulateRoundOfPlay(roundNum, roundName);

/* BEGIN COMMENTED-OUT CODE
 *      (can un-comment once simulateRoundOfPlay can read scores and
 *      proceed to a next round of play)

        // Simulate the number of rounds that were identified earlier.
        while ( roundNum < this.numRounds )
        {
            // Simulate a round of play.
            simulateRoundOfPlay(roundNum, roundName);

            // Prepare for next round.
            roundNum++;
            roundName = "Round " + roundNum;
        }
 * END COMMENTED-OUT CODE */

    }   // end of runTournament

/*
 * CODE MISSING!  Copy the getRankings and setRoundsAndByes methods
 *                from the initial Tournament class here.
 */

    /** Generates the tournament bracket, from the first round to the last.
     *      @param list the list of participants, ordered by ranking
     *      @return the tournament bracket (a tree of potential matchups)
     */
    private void generateBracket(K_SimpleList<ParticipantInfo> list)
    {
        // Make a list to hold the matchups for any full round (not bye).
        K_SimpleList<BracketTree> fullRoundMatchups = new K_SimpleAL<>();

        // Identify first-round byes (if any).  The highest ranked
        // participants do not have to participate in the bye round but
        // will participate in the first full round after the bye round.
        for ( int i = 0; i < this.numByes; i++ )
        {
            fullRoundMatchups.add(new BracketTree(list.get(i),
                                                  ParticipantInfo.BYE));
        }

        // Pass the participants who need to participate in the bye round
        // to determineMatchups.  The results of the bye round matches will
        // go on to the first full round.
        K_SimpleList<BracketTree> byeMatchups = new K_SimpleAL<>();
        for ( int i = this.numByes; i < list.size(); i++ )
            byeMatchups.add(new BracketTree(list.get(i)));
        byeMatchups = determineMatchups(byeMatchups);

        // Add all of the Bye matchups to the full bracket tree, so that
        // at this point, it contains all of the first-round matchups,
        // including byes and winners of bye-round matches.
        for ( BracketTree matchup : byeMatchups ) 
            fullRoundMatchups.add(matchup);

        // Keep generating the bracket from the bottom up until there
        // is only 1 match in the list (the final matchup).
        while ( fullRoundMatchups.size() > 1 )
        {
            fullRoundMatchups = determineMatchups(fullRoundMatchups);
        }

        // When fullRoundMatchups has only 1 matchup, the bracket is
        // complete.
        this.bracket = fullRoundMatchups.get(0);
    }

    /** Determines matchups for each round.
     *    @param lastRound the list of matchups from the previous round
     *    @return the new list of half as many matchups
     */
    private K_SimpleList<BracketTree>
                determineMatchups(K_SimpleList<BracketTree> lastRound)
    {

/*
 * CODE MISSING!  Copy and modify determineMatchups from Tournament class.
 */

    }

    /** Simulates a round of play: prints the matchups, reads in the
     *  scores, updates the bracket tree to identify the winners, and
     *  prints the results.
     *    @param roundNum  the round for which scores are needed
     *    @param roundName  the descriptor for the round
     *                      "Bye Round", "Round 1", etc.
     *    @throw java.io.IOException if there are errors reading files
     */
    private void simulateRoundOfPlay(int roundNum, String roundName)
            throws java.io.IOException
    {
        // Print the matches in this round.
        System.out.println(roundName + " Matches:");
        this.bracket.printNextMatchups();
        System.out.println();

        // If this is the bye round, participants who did not need to
        // participate get declared "winners".
        if ( roundNum == 0 )
            this.bracket.handleByes();

        // Get the scores from the given round and fill in bracket info.
/* BEGIN COMMENTED-OUT CODE (can un-comment once BracketScoresReader exists) 
        BracketScoresReader scoresReader = new BracketScoresReader();
        String filename = getScoresFilename(roundNum, roundName);
        scoresReader.readScores(filename, this.bracket);

        // Print results.
        System.out.println(roundName + " Results:");
        this.bracket.printRecentScores();
        System.out.println();
END COMMENTED-OUT CODE */
    }

    /** Prompts the user for the filename of the file containing scores for
     * the given round.
     *    @param roundNum  the round for which scores are needed
     *    @param roundName  the descriptor to use in the filename prompt
     *    @return the name of the file containing the round's scores
     */
    private String getScoresFilename(int roundNum, String roundName)
    {
        String suggestedName = "round" + roundNum + "Scores.txt";
        String filename =
            ValidatedInputReader.getString("File containing " +
                    roundName + " results: ", suggestedName);
        return filename;
    }

    public static void main(String[] args) throws java.io.IOException
    {
        Tournament2_0 tourney = new Tournament2_0();
        tourney.runTournament();
    }

}
