package tictactoe.pres;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import util.*;
import tictactoe.trans.TTTHandler;
import tictactoe.app.TTTApplication;

/**
 * A window containing a Tic-Tac-Toe board.  This can be used
 * to form the main presentation component of a Tic-Tac-Toe
 * application.  Extends the abstract class {@link ActionFrame}
 * so that the translation component can register without knowing
 * the exact structure of class <code>TTTFrame</code>
 *
 * @author Thomas P. Hayes
 * @version 1.0
 */
public class TTTFrame extends ActionFrame implements Runnable {

    public static final int EMPTY = TTTHandler.EMPTY;
    public static final int EX = TTTHandler.EX;
    public static final int OH = TTTHandler.OH;
    protected MasterPanel masterPanel;
    protected EditPanel editPanel;
    protected TTTGamePanel gamePanel;
    
    protected transient Vector listeners = null;
    
    /**
     * Contructs a new TTTFrame, and possibly displays it.
     *
     * @param doPackAndShow If <code>true</code>, the new window will
     * be readied and displayed; if <code>false</code>, it will not be
     * displayed.
     */
    public TTTFrame(boolean doPackAndShow) {
	Container cp = this.getContentPane();
	cp.setLayout(new BoxLayout(cp,BoxLayout.Y_AXIS));
	masterPanel = new MasterPanel();
	cp.add(masterPanel);
	editPanel = new EditPanel();
	cp.add(editPanel);
	gamePanel = new TTTGamePanel();
	cp.add(gamePanel);
	addListenerToPanels(this);
	if (doPackAndShow)
	    this.packAndShow();
    }
    
    /**
     * Resizes the window to fit its subcomponents, and makes the
     * window visible.
     */
    public void packAndShow() {
	this.pack();
	this.setVisible(true);
    }

    /**
     * Prepares the frame for public release, in serialized form.
     * Removes the editing tools from the display and from the
     * fields of the class (don't want these to serialize).
     *
     * @param doPackAndShow If <code>true</code>, resizes and refreshes
     * the window; if <code>false</code>, does not update the display.
     * This argument should be <code>true</code> unless you are closing
     * or hiding the window immediately.
     */
    public void finalize (boolean doPackAndShow) {
	Container cp = this.getContentPane();
	cp.removeAll();
	cp.add(gamePanel);
	masterPanel = null;
	if (doPackAndShow)
	    this.packAndShow();
    }

    public void editMode (boolean doPackAndShow) {
	Container cp = this.getContentPane();
	cp.removeAll();
	cp.add(masterPanel);
	cp.add(editPanel);
	cp.add(gamePanel);
	if (doPackAndShow)
	    this.packAndShow();
    }
    
    public void playMode (boolean doPackAndShow) {
  	Container cp = this.getContentPane();
	cp.removeAll();
	cp.add(masterPanel);
	cp.add(gamePanel);
	if (doPackAndShow)
	    this.packAndShow();
    }
    
    public void setMover (int who) {
	if (who == EX) 
	    gamePanel.setEnabledButtons(editPanel.xButton);
	else if (who == OH)
	    gamePanel.setEnabledButtons(editPanel.oButton);
	else
	    Debug.print("TTTFrame.setMover: Tried to set unknown mover.");
    }
    
    public void enableMove (int where, boolean moveAllowed) {
	gamePanel.enableMove(where, moveAllowed); 
    }

    public void addActionListener(ActionListener listener) {
	if (listeners == null)
	    listeners = new Vector();
	listeners.add(listener);
    }

    protected void addListenerToPanels(ActionListener listener) {
	if (masterPanel != null)
	    masterPanel.addActionListener(listener);
	editPanel.addActionListener(listener);
	gamePanel.addActionListener(listener);
    }

    public void actionPerformed(ActionEvent e) {
	if (listeners == null)
	    listeners = new Vector();
	for (Enumeration enum=listeners.elements(); enum.hasMoreElements();)
	    ((ActionListener)enum.nextElement()).actionPerformed(e);
    }
    
    public void startMenus() {
	setJMenuBar(editPanel.makeJMenuBar(this));
	packAndShow();
    }

    public void run() {
	startMenus();
	addListenerToPanels(this);
	if (listeners == null) {
	    TTTApplication app = new TTTApplication();
	    TTTHandler handler = new TTTHandler(this,app);
	    app.resetBoard();
	}
    }
    
    /**
     * Runs a quick test of the class code.
     *
     * @param args Command-line arguments (ignored).
     */
    public static void main (String[] args) {
	ActionFrame ttt = new TTTFrame(true);
	ttt.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

}






