/** An application that plays the game of Tetris.
 *
 * @author	Jim Grundy
 * @version	$Revision: 1.20 $ */

import java.awt.Frame;			// Frames, i.e screen windows.
import java.awt.Color;			// Colors.
import java.awt.BorderLayout;		// Layout information in a frame.
import java.awt.event.KeyAdapter;	// Adaptable keyboard event handling.
import java.awt.event.KeyEvent;		// Things that happen on the keyboard.

public class Tetris implements Runnable {
    
    private Frame display;		// Frame in which game is displayed.
    private TetrisField field;		// The field of tetris bricks
    private Brick brick;		// The current Tetris brick.
    private static final int WIDTH = 10;	// Width of a TetrisField.
    private static final int HEIGHT = 20;	// Height of a TetrisField.
    private static final int EDGE = 20;		// Size of a TetrisField tile.
    private static final Color BACKGROUND = Color.black;
    
    private final int DROP_DELAY = 900;	// Wait time(ms) after brick dropping.
    
    /* Create a new Tetris game. */
    private Tetris() {
	/* Create a frame to display the game and a TetrisField on which
	 * to play it.  Then, pack the field into the frame and display
	 * it.  */
	PlayingField tiles = new PlayingField(WIDTH,HEIGHT,EDGE,BACKGROUND);
	display = new Frame("Tetris");
	display.setLayout(new BorderLayout());
	display.add("North",tiles);
	display.pack();
	display.show();

	field = new TetrisField(tiles);
	brick = null;
	
	/* Keyboard events in the field are handled as follows: */
	tiles.addKeyListener
	    (new KeyAdapter()
	     {
		 public void keyPressed(KeyEvent e)
		     {
			 synchronized (field) {
			     if (brick == null) {
				 return;
			     }
			     
			     switch (e.getKeyCode()){
			     case KeyEvent.VK_UP:
				 brick.rotateRight();
				 break;
			     case KeyEvent.VK_DOWN:
				 brick.rotateLeft();
				 break;
			     case KeyEvent.VK_RIGHT:
				 brick.moveRight();
				 break;
			     case KeyEvent.VK_LEFT:
				 brick.moveLeft();
				 break;
			     case KeyEvent.VK_SPACE:
				 brick.plummet();
				 break;
			     case KeyEvent.VK_P:
				 System.out.println(brick.getField());
				 break;
			     case KeyEvent.VK_ESCAPE:
				 System.exit(0);
				 break;
			     }
			 }
		     }
	     });
    }
     
    /** Play the game of Tetris. */
    public void run()
    {
	/* While the playing field is not full, make a new brick and
	 * let it fall to the bottom. */
	while (!field.full()){
	    brick = new Brick(field);
	    boolean landed = false;
	    
	    /* While the brick hasn't landed drop it, pausing after drops
	     * to give the player a chance to move the brick. */
	    while (!landed){
	
		synchronized (field) {
		    brick.moveDown();
		}
		try {
		    Thread.sleep(DROP_DELAY);
		} catch (InterruptedException e) {
		    /* Just ignore interruptions. */
		}
		synchronized (field) {
		    landed = brick.hasLanded();
		    if (landed) {
			/* There is no brick now until next one is dropped */
			brick = null;
		    }
		}
	    }
	    
	    field.clearRows();
	}

	/* The field is full, so the game is over. */
	System.out.println("Game Over!");
	System.exit(0);
    }
  
  /** Create a Tetris game, and run it.
   *
   * @param args The command line arguments (ignored). */
  public static void main(String[] args) {
    Runnable game = new Tetris();
    new Thread(game).start();
  }
 
}

