/*  The Tortoise and the Hare Race
     Anderson, Franceschi
*/

import java.awt.*;
import javax.swing.*;
import java.util.ArrayList;

public class RacePoly extends JFrame
{
  private Racer [] racerList;
  private int numRacers;      // number of racers in array
  private static RacePoly app;
  private final int FIRST_RACER = 50;
  private int finishX; // location of finish line, dependent on window width
  private boolean raceIsOn = false;
  private RacePanel racePanel;

  /** Constructor
  *  instantiates list to track racers
  *  sets up GUI components
  */
  public RacePoly( )
  {
    super( "The Tortoise & The Hare!" );
    Container c = getContentPane( );
    racePanel = new RacePanel( );
    c.add( racePanel, BorderLayout.CENTER );

    racerList = new Racer[20];
    numRacers= 0;
    setSize( 400, 400 );
    setVisible( true );
  }

  /** prepareToRace method
  *   uses a dialog box to prompt user for racer types
  *     and to start the race
  *   racer types are 't' or 'T' for Tortoise,
  *                   'h' or 'H' for Hare
  *   's' or 'S' will start the race
  */
  private void prepareToRace( )
  {
     int yPos = FIRST_RACER;        // y position of first racer
     final int START_LINE = 40;     // x position of start of race
     final int RACER_SPACE = 50;    // spacing between racers
     char input;

     input = getRacer( ); // get input from user

     while ( input != 's' && input != 'S' )
     {
        if (input=='t' || input=='T') {
          racerList[numRacers]= new Tortoise("T Sam",START_LINE,yPos);
          numRacers++;
          yPos+= RACER_SPACE;
        }
        else if (input=='h' || input=='H') {
          racerList[numRacers]= new Hare("H Fred",START_LINE,yPos);
          numRacers++;
          yPos+= RACER_SPACE;
        }
        else
          JOptionPane.showMessageDialog( this, "Must enter either 't' or 'h' or 's'" );

       repaint( );
       input = getRacer( ); // get input from user

     } // end while
   }



   private class RacePanel extends JPanel
   {
    /** paint method
    *    @param g   Graphics context
    *    draws the finish line;
    *    moves and draws racers
    */
    public void paintComponent( Graphics g )
    {
      super.paintComponent( g );

      // draw the finish line
      finishX = getWidth( ) - 20;
      g.setColor( Color.blue );
      g.drawLine( finishX, 0, finishX, getHeight( ) );

      if ( raceIsOn )
      {
         for (int i=0; i<numRacers; i++) {
           racerList[i].move();
           racerList[i].draw(g);
         }
      }
      else // display racers before race begins
      {
         for (int i=0; i<numRacers; i++)
           racerList[i].draw(g);
      }
    }
  }

   /** runRace method
   *  checks whether any racers have been added to racerList
   *  if no racers, exits with message
   *  otherwise, runs race, calls repaint to move & draw racers
   *  calls reportRaceResults to identify winners(s)
   *  calls reset to set up for next race
   */
   public void runRace( )
   {
       if (numRacers==0)
       {
            JOptionPane.showMessageDialog( this,
                  "The race has no racers. exiting",
                  "No Racers", JOptionPane.ERROR_MESSAGE );
            System.exit( 0 );
       }
       raceIsOn = true;
       while ( ! findWinner( ) )
       {
           Pause.wait(.03);
           repaint( );
       } // end while

       reportRaceResults( );
       reset( );
   }

  /** gets racer selection from user
  *   @return  first character of user entry
  *            if user presses cancel, exits the program
  */
  private char getRacer( )
  {
      String input = JOptionPane.showInputDialog( this, "Enter a racer:"
                                          + "\nt for Tortoise, h for hare,"
                                          + "\nor s to start the race" );
      if ( input == null )
      {
         System.out.println( "Exiting" );
         System.exit( 0 );
      }
      if ( input.length( ) == 0 )
         return 'n';
      else
         return input.charAt( 0 );
  }

  /** findWinners:
  *    checks for any racer whose x position is past the finish line
  *    @return  true if any racer's x position is past the finish line
  *             or false if no racer's x position is past the finish line
  */
  private boolean findWinner( )
  {
    for ( int i=0; i<numRacers; i++)
    {
      if ( racerList[i].getX( ) > finishX  )
        return true;
    }
    return false;
  }

  /** reportRaceResults : compiles winner names and prints message
  *   winners are all racers whose x position is past the finish line
  */
  private void reportRaceResults( )
  {
    raceIsOn = false;
    String results = "Racer ";
    for ( int i = 0; i < numRacers; i ++ )
    {
      if ( racerList[i].getX( ) > finishX  )
      {
         results += ( i + 1 )  + ", a " + racerList[i].getID( ) + ", ";
      }
    }

    JOptionPane.showMessageDialog( this,  results + " win(s) the race " );

  }

  /** reset:  sets up for next race:
  *       sets raceIsOn flag to false
  *       clears the list of racers
  *       resets racer position to FIRST_RACER
  *       enables checkboxes and radio buttons
  */
  private void reset( )
  {
      char answer;
      String input = JOptionPane.showInputDialog( this, "Another race? (y, n)" );
      if ( input == null || input.length( ) == 0 )
      {
          System.out.println( "Exiting" );
          System.exit( 0 );
      }

      answer = input.charAt( 0 );
      if ( answer == 'y' || answer == 'Y' )
      {
          raceIsOn = false;
          numRacers= 0;
          app.prepareToRace( );
          app.runRace( );
      }
      else
          System.exit( 0 );
  }

  /** main
  *   instantiates the RacePoly object app
  *   calls runRace method
  */
  public static void main( String [] args )
  {
     app = new RacePoly( );
     app.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
     app.prepareToRace( );
     app.runRace( );
  }
}
