// Final3 for CSII of S'98
// Tennis.java - Tennis Game

import java.applet.Applet;
import java.applet.*;
import java.awt.Graphics;
import java.awt.Polygon;
import java.awt.event.*;
import java.awt.*;

public class Tennis extends Applet
            implements  Runnable, ActionListener, ItemListener
{
   private int score_A =1000, score_B = 1000;
   private int x1[] = { 80, 480, 420, 20, 80 };
   private int y1[] = { 25, 25, 225, 225, 25 };
   private int x2[] = { 280, 220, 200, 260, 280 };
   private int y2[] = { 25, 225, 205, 5, 25 };
   private int x3[] = { 280, 80, 20, 220, 280 };
   private int y3[] = { 25, 25, 225, 225, 25 };
   private int x4[] = { 280, 480, 420, 220, 280 };
   private int y4[] = { 25, 25, 225, 225, 25 };

   private Point A1, A2, A3, A4, B1, B2, B3, B4, temp, origin;
   private Polygon p1, p2, p3, p4;
   private TextField scoreA, scoreB;

   private Image ball;
   private Panel radioPanel;
   private Button fireA, fireB;
   private CheckboxGroup distA, distB, sideA, sideB,
                         heightA, heightB, speedA, speedB;
   private Checkbox farA, farB, closeA, closeB,
                    leftA, leftB, rightA, rightB,
                    highA, highB, lowA, lowB,
                    fastA, fastB, slowA, slowB;

   private canvas c;

   private Thread td;
   private boolean sd = false, sd1 = false, sd2 = true, sdA, side;
   private ColorFrame info;
   private AudioClip sound1, sound2;

   public void init()
   {
      sound1 = getAudioClip( getDocumentBase(), "gong.au" );
      sound2 = getAudioClip( getDocumentBase(), "joy.au" );

      info = new ColorFrame();
      info.setVisible( true );
      A1 = new Point( 120, 60 );
      A2 = new Point( 90, 180 );
      A3 = new Point( 210, 60 );
      A4 = new Point( 180, 180 );
      B1 = new Point( 420, 62 );
      B2 = new Point( 350, 182 );
      B3 = new Point( 320, 62 );
      B4 = new Point( 280, 182 );
      temp = new Point( 120 , 60 );
      p1 = new Polygon( x1, y1, 5);
      p2 = new Polygon( x2, y2, 5 );
      p3 = new Polygon( x3, y3, 5);
      p4 = new Polygon( x4, y4, 5 );

      fireA = new Button( "Side A To Fire !" );
      fireB = new Button( "Side B To Fire !" );

      scoreA = new TextField("1000", 20 );
      scoreB = new TextField("1000", 20 );
      scoreA.setEditable( false );
      scoreB.setEditable( false );

      fireA.addActionListener( this );
      fireB.addActionListener( this );

      distA = new CheckboxGroup();
      sideA = new CheckboxGroup();
      heightA = new CheckboxGroup();
      speedA = new CheckboxGroup();

      farA = new Checkbox( "far", distA, true );
      closeA = new Checkbox( "close", distA, false );
      leftA = new Checkbox( "left", sideA, true );
      rightA = new Checkbox( "right", sideA, false );
      highA = new Checkbox( "high", heightA, false );
      lowA = new Checkbox( "low", heightA, true );
      slowA = new Checkbox( "slow", speedA, true );
      fastA = new Checkbox( "fast", speedA, false );

      farA.addItemListener( this );
      closeA.addItemListener( this );
      leftA.addItemListener( this );
      rightA.addItemListener( this );
      highA.addItemListener( this );
      lowA.addItemListener( this );
      slowA.addItemListener( this );
      fastA.addItemListener( this );

      radioPanel = new Panel();
      radioPanel.setLayout( new GridLayout( 5, 4 ) );
      radioPanel.add( fireA );
      radioPanel.add( scoreA );
      radioPanel.add( scoreB );
      radioPanel.add( fireB );
      radioPanel.add( new Label( " " ) );
      radioPanel.add( new Label( " " ) );
      radioPanel.add( new Label( " " ) );
      radioPanel.add( new Label( " " ) );

      radioPanel.add( new Label( "Distance" ) );
      radioPanel.add( new Label( "Side" ) );
      radioPanel.add( new Label( "Height" ) );
      radioPanel.add( new Label( "Speed" ) );

      radioPanel.add( farA );
      radioPanel.add( leftA );
      radioPanel.add( lowA );
      radioPanel.add( slowA );
      radioPanel.add( closeA );
      radioPanel.add( rightA );
      radioPanel.add( highA );
      radioPanel.add( fastA );

      ball = getImage (getDocumentBase(), "star.gif" );
      c = new canvas( ball );
      add( c );
      c.setLocation( -10, 0 );

      setBackground( Color.red );
      setSize( 500, 380 );
      setLayout( new BorderLayout() );
      add( radioPanel, BorderLayout.SOUTH );

   }

   public void start()
   {
      td = new Thread( this, "td" );
      td.start();
   }

   public void stop()
   {
      td.stop();
   }

   public void paint( Graphics g )
   {
      g.setColor( Color.blue );
      g.drawString( "Side A", 160, 10 );
      g.drawString( "Side B", 360, 10 );

      g.setColor( Color.green);
      g.fillPolygon( p1 );
      g.setColor( Color.blue);
      g.fillPolygon( p2 );
      g.setColor( Color.white);

      g.drawLine( 80, 25, 254, 25 );
      g.drawLine( 280, 25, 480, 25 );
      g.drawLine( 480, 25, 420, 225 );
      g.drawLine( 420, 225, 20, 225 );
      g.drawLine( 80, 25, 20, 225 );
      g.drawLine( 80, 24, 254, 24 );
      g.drawLine( 280, 24, 480, 24 );
      g.drawLine( 481, 25, 421, 225 );
      g.drawLine( 420, 226, 20, 226 );
      g.drawLine( 79, 25, 19, 225 );
 
      g.setColor( Color.yellow );
      g.drawLine( 50, 125, 224, 125 );
      g.drawLine( 250, 125, 450, 125 );
      g.drawLine( 220, 25, 160, 225 );
      g.drawLine( 340, 25, 280, 225 );
   }

   public void actionPerformed( ActionEvent e )
   {
     sd1 = false;

     if( e.getSource() == fireA )
     {       
       sdA = true;
       if( ! p3.contains( temp.getX(), temp.getY() ) || sd2 == false || side == true )
       {
         scoreA.setText( Integer.toString( score_A-- ) );
         temp.setPoint( 120, 60 );
         sound1.play();
         sound2.stop();
         sd = false;
         sd2 = true;
         side = false;
       }
       else
       {
         sd = true;
         side = true;
       }
     }
     else 
     {
       sdA = false;
       if( ! p4.contains( temp.getX(), temp.getY() ) || sd2 == false || side == false )
       {
         temp.setPoint( 420, 60 );
         scoreB.setText( Integer.toString( score_B-- ) );
         sound1.play();
         sound2.stop();
         sd = false;
         side = true; 
         sd2 = true;
       }
       else
       {
         sd = true;
         side = false;
       }
     }
  }



  public void itemStateChanged( ItemEvent e )
  {
    sd = false;
  }

   public void run()
   {
      while ( true )
      {

         try
         {
            Thread.sleep( 1 );
         }
         catch ( InterruptedException e )
         {
            e.printStackTrace();
         }     

         temp.setPoint( temp.getX(), temp.getY() );
         c.setLoc( temp.getX(), temp.getY() ); 

         if( sd && sdA )
         {
            if( farA.getState() && leftA.getState() && slowA.getState() )
            {
               removeBall( temp, B1, 1.0 );
            }
               else if( ! farA.getState() && leftA.getState() && slowA.getState() )
            {
               removeBall( temp, B3, 1.0 );
            }
            else if( farA.getState() && ! leftA.getState() && slowA.getState() )
            {
               removeBall( temp, B2, 1.0 );
            }
            else if( farA.getState() && leftA.getState() && ! slowA.getState() )
            {
               removeBall( temp, B1, 2.0 );
            }
            else if( farA.getState() && ! leftA.getState() && ! slowA.getState() )
            {
               removeBall( temp, B2, 2.0 );
            }
            else if( ! farA.getState() && ! leftA.getState() && slowA.getState() )
            {
               removeBall( temp, B4, 1.0 );
            }
            else if( ! farA.getState() && leftA.getState() && ! slowA.getState() )
            {
               removeBall( temp, B3, 2.0 );
            }
            else if( ! farA.getState() && ! leftA.getState() && ! slowA.getState() )
            {
               removeBall( temp, B4, 2.0 );
            }
         }

         else if( sd && ! sdA )
         {
            if( farA.getState() && leftA.getState() && slowA.getState() )
            {
              removeBall( temp, A1, 1.0 );
            }
            else if( ! farA.getState() && leftA.getState() && slowA.getState() )
            {
              removeBall( temp, A3, 1.0 );
            }
            else if( farA.getState() && ! leftA.getState() && slowA.getState() )
            {
              removeBall( temp, A2, 1.0 );
            }
            else if( farA.getState() && leftA.getState() && ! slowA.getState() )
            {
              removeBall( temp, A1, 2.0 );
            }
            else if( farA.getState() && ! leftA.getState() && ! slowA.getState() )
            {
              removeBall( temp, A2, 2.0 );
            }
            else if( ! farA.getState() && ! leftA.getState() && slowA.getState() )
            {
              removeBall( temp, A4, 1.0 );
            }
            else if( ! farA.getState() && leftA.getState() && ! slowA.getState() )
            {
              removeBall( temp, A3, 2.0 );
            }
            else if( ! farA.getState() && ! leftA.getState() && ! slowA.getState() )
            {
              removeBall( temp, A4, 2.0 );
            }
         }               
      }
   }

   public void removeBall( Point p, Point q, double k )
   {
     int x1 = p.getX();
     int y1 = p.getY();
     int x2 = q.getX();
     int y2 = q.getY();
     int m = ( Math.abs( x1-x2 ) == Math.max( Math.abs( x1-x2 ), Math.abs( y1-y2 ) ) ) ? Math.abs( x1-x2 ) : Math.abs( y1-y2 ); 
     double n = 1.0 / (double) m;
     int x = x1;
     int y = y1;

     sd1 = true;
     sound1.stop();
     sound2.play();

     for( double i = 0.0; i < (double) m; i = i + k )
     {
       try
       {
         td.sleep( 10 );
         temp.setPoint( x, y );
         c.setLoc( temp.getX(), temp.getY() );
         x = x1 + (int)( (double)( x2 - x1 ) * n * i );
         y = y1 + (int)( (double)( y2 - y1 ) * n * i );
         sd2 = true;
         if( sd1 == false )
            break;
       }

       catch ( InterruptedException e )
       {
         e.printStackTrace();
       }     
     }
     sd2 = false;
  }
}

class Point 
{
   private int x, y;

   public Point() { setPoint( -10, 0 ); }

   public Point( int a, int b ) { setPoint( a, b ); }

   public void setPoint( int a, int b )
   {
      x = a;
      y = b;
   }

   public int getX() { return x; }

   public int getY() { return y; }
}

class canvas extends Canvas
{
   private Image ball;

   public canvas( Image m )
   {                            
      setSize( 10, 10 );
      setBackground( Color.green );
      ball = m;
   }
    
   public void setLoc(int i, int j )
   {
      setLocation( i, j );
   }

   public void paint( Graphics g )
   {
      g.drawImage( ball, 0, 0, this );
   }
}

class ColorFrame extends Frame {
   private TextArea t;
   private String ss;

   public ColorFrame()
   {
      super( "Play Rule" );
      setSize( 75, 350 );
      setLocation(480, 0);
      ss = new String (" Start from Side A or Side B to fire, alternatively fire A or B before the ball stops. You can change the Speed, distance, and side before each firing. If the ball is not at the same side as the one from which you fire, the side will lose two points. Also the side where the ball stops will lose two points. " );

      t = new TextArea( ss, 2, 20,
                        TextArea.SCROLLBARS_VERTICAL_ONLY);
      
      add( t, BorderLayout.CENTER );
 
      addWindowListener( new CloseWindow() );
   }

}

class CloseWindow extends WindowAdapter {
   public void windowClosing( WindowEvent e )
   {
      e.getWindow().setVisible( false );
   }
}