package gizmoball.ui;

import gizmoball.game.GameBoard;
import gizmoball.ui.r2.R2PlayingInteractionMode;

import java.awt.Graphics;
import java.awt.event.KeyListener;

import javax.swing.JComponent;
import javax.swing.JPanel;

import staffui.MagicKeyListener;

/**
 * Abstract base class for representing GameBoard displays.  This class
 * is extended to create all variants of graphical representations of
 * Gizmoball boards (for now, just the R2).  Basic features universal
 * to all boards are incorporated. <p>
 * 
 * All GameBoardComponents will have interaction modes that determine
 * how input from the user is handled.  Internally, any instance of
 * an AbstractInteractionMode may be swapped into interfacing with the
 * GameBoardComponent, but externally, modes are limited to those
 * enumerated by InteractionModeTypes. <p>
 *
 * All GameBoardComponents also have a method to access a panel containing
 * the palette of gizmos placeable onto the GameBoards they display. <p> 
 *
 * @see AbstractInteractionMode
 * @see InteractionModeType
 * @author Albert Leung
 * @version $Id: AbstractGameBoardComponent.java,v 1.12 2004/04/28 01:47:31 aleung Exp $
 * 
 */

abstract public class AbstractGameBoardComponent extends JComponent {

	private AbstractInteractionMode mode;
	private GameBoard gameboard;

	public AbstractGameBoardComponent() {
		this.setCurrentInteractionMode(new R2PlayingInteractionMode(this));
		this.gameboard = new GameBoard();
	}
	
	/**
	 * Create a Gizmo toolbar/palette based on the collection of placeable
	 * gizmos for the current AbstractGameBoardComponent.
	 * 
	 * @return a JPanel containing the set of placeable gizmos
	 *  
	 */
	abstract public JPanel createGizmoPalette();
	
	/**
	 * Internal method used to switch between interaction modes observing
	 * an AbstractGameBoardComponent.
	 * 
	 * @param mode the AbstractInteractionMode to set as the active mode
	 * 
	 */
	protected void setCurrentInteractionMode(AbstractInteractionMode mode) {
		this.mode = mode;
		KeyListener[] kl = this.getKeyListeners();
		for (int i = 0; i < kl.length; i++) {
			this.removeKeyListener(kl[i]);
		}
		this.addKeyListener(new MagicKeyListener(mode));
	}
	
	/**
	 * External method used to switch between interaction mode types (as
	 * enumerated by {@link InteractionModeType InteractionModeTypes}).
	 * 
	 * @requires InteractionModeType.TYPES.contains(type)
	 * @param type the type of interaction mode to switch to
	 * 
	 */
	abstract public void setMode(InteractionModeType type);
	
	/**
	 * Accessor for the current interaction mode.
	 * 
	 * @return the interaction mode currently listening to this
	 * AbstractGameBoardComponent
	 * 
	 */
	AbstractInteractionMode getCurrentInteractionMode() {
		return mode;
	}
	
	/**
	 * Accessor for the current gameboard.
	 * 
	 * @return the gameboard currently being displayed by the
	 * abstract component.
	 * 
	 */
	public GameBoard getGameBoard() {
		return gameboard;
	}

	/**
	 * Mutator for the current gameboard.
	 * 
	 * @param board the new gameboard to set as the current
	 * gameboard for the component. 
	 * 
	 */
	public void setGameBoard(GameBoard board) {
		if (board != null) {
			gameboard = board;
		}
		//else signal error?
	}
	
	/**
	 * Drawing method for all aspects of the gameboard.
	 * Implementations must handle the painting of gizmos
	 * and other elements onto the component.
	 * 
	 * @param g the Graphics context on which elements are 
	 * drawn
	 * 
	 */
	abstract public void paint(Graphics g);
}
