/**
 *  Selim Mimaroglu
 *
 *  CS680 "Object-Oriented Programming"
 *  Programming Assignment "Marble Applet"
 *
 *  Spring 2002
 *  File: ~smimarog/cs680/p3/Marble.java
 *
 */





import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.URL;

/**
 * @author Selim Mimaroglu
 * @version 1.0
 *
 * "Marble" is responsible for driving Marble Game
 *  It has many swing components like JButton and JLabel. "Marble" class
 *  gets input from user and send necessary commands to other classes.
 *
 */


public class Marble extends JApplet {

    // MarbleGround and Animator objects of "Marble" class
    // Framework "Object Oriented Software Development Using Java" textbook
    // animation framework is used
    /**
     * It's a JPanel, where marble game takes place
     */
    protected MarbleGround canvas; 

    /**
     * Animator object drives applet
     */
    protected Animator animator;

    /**
     * JPanel where control buttons are located
     */
    protected JPanel controlPanel;

    
    /**
     * JButtons for starting a new game, shooting a marble, clearing marks
     * turning left
     */
    private JButton newGameButton, shootButton, clearMarksButton, leftButton;

    /**
     * buttons for turning right and lagging
     */
    private JButton rightButton, lagButton;

    /**
     * JLabels for keeping score of the players. Also these labels have images
     * for specifying the player
     */
    private JLabel player1Score, player2Score, one , two;

    /**
     * mouse listener of the applet
     */
    private TableListener tableListener;

    /**
     * when lagging, lag = true, otherwise lag = false
     */
    private boolean lag = false;

    /**
     * if it's in lag state, each ball may do only one shot
     * totally two shots will be done in lag state
     */
    private int lagShot = 0;

    /**
     * default constructor of "Marble". It creates control panel,
     * score panel and playing panel(at the center). Puts "Marble
     * Game" in playing panel. Score for player1 and player2 in score
     * panel. It has the following control buttons:
     *  - New Game
     *  - Lag
     *  - Shoot
     *  - Clear Marks
     *  - Left
     *  - Right
     *
     * It has following scores in the score panel
     *  - Player1 score
     *  - Player2 score
     */
    public Marble() {
		
	// get Content Pane, set layout add marble ground
	Container contentPane = getContentPane();
	contentPane.setLayout(new BorderLayout());
	canvas = new MarbleGround();
	contentPane.add(canvas, BorderLayout.CENTER);

	animator = new Animator(canvas);

	// score Panel
	// it will modify itself depending on new scores
	JPanel scorePanel = new JPanel();
	scorePanel.setLayout(new GridLayout(1,0));
	one = new JLabel("Player1 Score:");
	player1Score = new JLabel("0");
        two = new JLabel("Player2 Score:");
	player2Score = new JLabel("0");
	scorePanel.add(one);
	scorePanel.add(player1Score);
	scorePanel.add(two);
	scorePanel.add(player2Score);

	// control Panel, add necessary control buttons
	controlPanel = new JPanel();
	controlPanel.setLayout(new GridLayout(1,0) );
	newGameButton = new JButton("New Game");
	controlPanel.add(newGameButton);
	lagButton = new JButton("Lag");
	controlPanel.add(lagButton);
	shootButton = new JButton("Shoot");
	controlPanel.add(shootButton);
	clearMarksButton = new JButton("Clear Marks");
	controlPanel.add(clearMarksButton);
	leftButton = new JButton("Left");
	controlPanel.add(leftButton);
	rightButton = new JButton("Right");
	controlPanel.add(rightButton);

	// holding Panel, 
	// holds control Panel and score Panel
	JPanel holdPanel = new JPanel();
	holdPanel.setLayout(new GridLayout(2,1));
	holdPanel.add(controlPanel);
	holdPanel.add(scorePanel);

	contentPane.add(holdPanel, BorderLayout.SOUTH);

	// register buttons to event handlers
	ButtonHandler buttonHandler = new ButtonHandler();
	tableListener = new TableListener();

	lagButton.addActionListener(buttonHandler);
	newGameButton.addActionListener(buttonHandler);
	shootButton.addActionListener(buttonHandler);
	clearMarksButton.addActionListener(buttonHandler);
	rightButton.addActionListener(buttonHandler);
	leftButton.addActionListener(buttonHandler);

    }


    /**
     * overwrites init of the JApplet
     * gets the animation delay parameter from "Marble.html", has default
     * values too (in case of bad initilaization). Initializes "MarbleGround".
     * Calls resetGame() method
     * which resets all the JButtons and JLabels (score)
     *
     */
    public void init() {
	URL codebase =getCodeBase();
	
	// this section is for setting label gifs
	URL firstURL = null, secondURL = null;
	
	try{
	    firstURL = new URL(codebase, "violetball.gif");
	    secondURL = new URL(codebase, "yellowball.gif");
	} catch ( java.net.MalformedURLException e) {
	    System.err.println("couldn't create image: " + "badly specified URL");
	}
	ImageIcon icon1 = new ImageIcon(firstURL, "first shooter");
	ImageIcon icon2 = new ImageIcon(secondURL, "second shooter");

	one.setIcon(icon1);
	two.setIcon(icon2);
	

	int delay = -1;
	String param = getParameter("delay");
	if ( param != null ) {
	    delay = Integer.parseInt(param);
	}
	doLayout();
	canvas.initCanvas(delay, codebase);

	//reset game
	resetGame();
    }

    /**
     * Calls start() of Animator object, which implements runnable
     * Mainly it creates and starts a thread
     */
    public void start() {
	animator.start();
    }

    /**
     * Calls stop() of Animator object, which implements runnable
     * Mainly it makes the thread null
     */
    public void stop() {
	animator.stop();
    }


    /**
     * Creates all initial states of JButtons and JLabels
     * adds mouse listener to 
     * @see MarbleGround 
     * object where Marble Game
     * takes place. Calls resetTable of MarbleGround
     */
    private void resetGame() {
	// reset player1 and player2 score
	player1Score.setText("0");
	player2Score.setText("0");

	// disable clear and shoot buttons
	lagButton.setEnabled(true);
	leftButton.setEnabled(true);
	rightButton.setEnabled(true);
	shootButton.setEnabled(false);
	clearMarksButton.setEnabled(false);
	canvas.addMouseListener(tableListener);
	canvas.resetTable();
    }

    /**
     * When shoot button in control Panel is clicked, this
     * method is called it calls 
     * @see MarbleGround shootBall()
     * Asks the player and it's score to @see MarbleGround
     * whoIsPlaying() and whatIsScore()
     *
     */
    private void handleShootBall() {

	/**
	 * When lagging starts, it should be completed,
	 * It's in lagging state below. End lagging state after
	 * second shot.
	 */
	if ( lag && lagShot != 2) {
	    lagShot++;

	    if( lagShot == 2) {
		lag = false;
		lagShot = 0;
		leftButton.setEnabled(true);
		rightButton.setEnabled(true);
		newGameButton.setEnabled(true);
	    }
	}
	else if ( !lag ) {

	    lagButton.setEnabled(false);
	    //newGameButton.setEnabled(true);
	    rightButton.setEnabled(false);
	    leftButton.setEnabled(false);
	}

	shootButton.setEnabled(false);
	clearMarksButton.setEnabled(false);
	canvas.removeMouseListener(tableListener);

	// shoot the ball
	canvas.shootBall();

	// get player and score for modifying score board
	int player = canvas.whoIsPlaying();
	int score = canvas.whatIsScore();

	// modify score board
	modifyScore(player, score);

	canvas.addMouseListener(tableListener);
	canvas.clearMarks();
	System.gc();   //for performance
    }


    /**
     * This method clears the second mark.
     * First mark is the shooter itself, user puts the second mark.
     * 
     */
    private void handleClearMarks() {
	clearMarksButton.setEnabled(false);
	shootButton.setEnabled(false);
	canvas.clearMarks();
    }

    /**
     * Initial positions of the balls are drawn at start. User is able
     * to start from anywhere, on the circle. This method, moves the
     * 13 marbles to angular left position by 45 degrees.
     */
    private void handleLeftTurn() {
	canvas.turnLeft();
    }



    /**
     * Initial position of the balls are drawn at start. User is able
     * to start from anywhere, on the circle. This method, moves the
     * 13 marbles to angular right position by 45 degrees.
     */
    private void handleRightTurn() {
	canvas.turnRight();
    }



    /**
     * When "Lag" button is pressed this method is called.
     * it calls doLagging() method in
     * @see MarbleGround
     * Activate and deactivate some of some buttons.
     */
    private void handleLagging() {

	// we are lagging, no lag shot is done yet
	lag = true;
	lagShot = 0;

	//disable some buttons
	newGameButton.setEnabled(false);
	leftButton.setEnabled(false);
	rightButton.setEnabled(false);

	// do lagging
	canvas.doLagging();

	// after lagging is done enable buttons
	newGameButton.setEnabled(false);
	lagButton.setEnabled(false);
    }


    /**
     * This method is called from handleShootBall() method. When
     * a shot is done, it's possible that score will be modified
     *
     * @param player scorer
     * @param score score of scorer
     */
    private void modifyScore(int player, int score) {

	// if it is lagging don't modify the score
	if( player == 0 ) {
	    return;
	}

	// winner!, reset the game
	else if ( player == 3 ) {
	    resetGame();
	}

	// player1 scored someothing
	else if( player == 1) {
	    String scoreText = player1Score.getText();
	    int integerScore = Integer.parseInt(scoreText);

	    // modify score
	    integerScore += score;
	    Integer setScore = new Integer(integerScore);
	    player1Score.setText(setScore.toString());
	}

	// palyer2 scored something
	else if( player == 2) {
	    String scoreText = player2Score.getText();
	    int integerScore = Integer.parseInt(scoreText);

	    // modify score
	    integerScore += score;
	    Integer setScore = new Integer(integerScore);
	    player2Score.setText(setScore.toString());
	}
    }


    /**
     * Button Listener, depending on which button is pressed
     * calls appropriate handlers
     *
     * @author Selim Mimaroglu
     * @version 1.0
     *
     * This class handle all the actions of that should be done
     * when a button is pressed.
     */
    protected class ButtonHandler implements ActionListener {
	public void actionPerformed(ActionEvent event) {

	    if( "New Game".equals(event.getActionCommand()) ) {
		resetGame();
	    }
	    else if ("Shoot".equals(event.getActionCommand()) ) {
		handleShootBall();
	    }
	    else if("Clear Marks".equals(event.getActionCommand()) ) {
		handleClearMarks();
	    }
	    else if("Left".equals(event.getActionCommand()) ) {
		handleLeftTurn();
	    }
	    else if("Right".equals(event.getActionCommand()) ) {
		handleRightTurn();
	    }
	    else if("Lag".equals(event.getActionCommand()) ) {
		handleLagging();
	    }
	}
    }


    /**
     * Mouse Listener, handles setting marks on the marble ground
     *
     * @author Selim Mimaroglu
     * @version 1.0
     *
     * Impelements mouse events, set a mark on the table
     * where mouse is clicked
     */
    protected class TableListener extends MouseAdapter {
	public void mouseClicked( MouseEvent e) {
	    Point where = e.getPoint();
	    int nmarks = canvas.setMark(where.x, where.y);
	    if ( nmarks > 1 ) {
		clearMarksButton.setEnabled(true);
	    }
	    if ( nmarks == 2 ) {
		shootButton.setEnabled(true);
	    }
	}
    }


}


