import java.util.Objects;

/**
 *  ParticipantInfo class:
 *  The ParticipantInfo class contains an athlete's or team's name, their
 *  ranking, and their most recent score.  Participants can be ordered by
 *  their ranking, with their name as a secondary ordering value in case of
 *  a tie.  
 *
 *  This class assumes that a participant's name uniquely identifies them,
 *  so there should never be two participants with the same name.
 *
 *  @author Alyce Brady
 *  Creation Date: Fall 2025
 */
public class ParticipantInfo implements Comparable<ParticipantInfo>
{
    private String name;
    private Integer ranking;
    private Integer recentScore;

    /** Constructs an ParticipantInfo instance with the given name and
     *  empty ranking and recent scores.  (This is used to find
     *  participants in a list based solely on their name.)
     *      @param name  a participant's name
     */
    public ParticipantInfo (String name)
    {
        this.name = name;
        this.ranking = null;
        this.recentScore = null;
    }

    /** Constructs a ParticipantInfo instance with the given name and
     *  ranking.
     *      @param name     the participant's name
     *      @param ranking  the participant's ranking
     */
    public ParticipantInfo (String name, Integer ranking)
    {
        this.name = name;
        this.ranking = ranking;
        this.recentScore = null;
    }

    /** Returns the participant's name.
     *      @return the participant's name
     */
    public String getName()
    {
        return this.name;
    }

    /** Returns the participant's ranking.
     *      @return the participant's ranking
     */
    public Integer getRanking()
    {
        return this.ranking;
    }

    /** Returns the participant's most recent score.
     *      @return the participant's most recent score
     */
    public Integer getScore()
    {
        return this.recentScore;
    }

    /** Updates the participant's most recent score.
     *      @param newScore the participant's most recent score
     */
    public void setScore(Integer newScore)
    {
        this.recentScore = newScore;
    }

    public String rankThenName()
    {
        return this.ranking + ". " + this.name;
    }

    public String nameThenScore()
    {
        return  rankThenName() +
                ((this.recentScore == null )
                    ? ""
                    : " (" + this.recentScore + ")");
    }

    /** {@inheritDoc}
     *  Compares two participants based on the integer value (e.g., rank or
     *  score), using participants' names to break ordering ties.
     */
    @Override
    public int compareTo(ParticipantInfo otherParticipant)
    {
        // If the names are the same (should never happen), the two objects
        // are considered equal.
        if ( this.name.equals(otherParticipant.name) )
            return 0;

        // Compare based on the participants' rankings.
        int comparison = this.ranking.compareTo(otherParticipant.ranking);

        // If values are equal, the secondary comparison is based on name.
        if ( comparison == 0 )
            comparison = this.name.compareTo(otherParticipant.name);

        return comparison;
    }

    /** {@inheritDoc}
     *  Determines equality based solely on the name field; two instances
     *  with the same name are considered equal.  The assumption is that
     *  participants have unique names.
     */
    @Override
    public boolean equals(Object other)
    {
        // 1. Quick check: If the references are identical, they are equal.
        if (this == other) return true;

        // 2. Type check: If 'other' is null or not of the same class, they
        // are not equal.
        if (other == null || getClass() != other.getClass()) return false;

        // 3. Cast: The object 'other' is now confirmed to be another
        // ParticipantInfo object.
        ParticipantInfo otherParticipant = (ParticipantInfo) other;

        // 4. Field comparison: Compare the fields that define equality.
        //    Use Objects.equals() to handle potential null values gracefully.
        return Objects.equals(this.name, otherParticipant.name);
    }

    /** {@inheritDoc}
     *  Must override hashCode() when overriding equals().
     */
    @Override
    public int hashCode()
    {
        // Generate a hash code based ONLY on the field(s) used in equals().
        return Objects.hash(this.name);
    }

}
