/**
 * JavaLife - Conway's Life Simulation
 * @author Scott Hurring - scott at hurring dot com
 * @version alpha1
 * @license GPL
 * For most recent version, go to this url:
 * http://hurring.com/code/java/javalife/
 */

import java.awt.Color;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Vector;

import javax.swing.JLabel;
import javax.swing.border.LineBorder;

/**
 * A single life cell.
 * 
 * Changes should only be commit()ed to a cell after all generation 
 * computations to all cells on the field are done.
 * 
 * Life is discrete, changes can only happen per-generation, a change
 * made to a cell cannot have any affect until the next generation is 
 * computed, which is why states that are set() by the engine must
 * then be commit()'d to the cell *after* all computations are done.
 *
 * For example: if [1][1] is computed to die and its state is immediadely 
 * changed, when [1][2] is computed, the neighbor count is wrong.
 * 
 * Extends JLabel becuase it was an easy way to have the cell know 
 * how to draw itself
 */
class LifeCell extends JLabel 
{	
	public boolean state = false;
	public boolean newstate = false;
	private static Color aliveColor = new Color(200,200,255);
	private static Color deadColor = new Color(255,255,255);
	private static Color borderColor = new Color(200,200,200);
	private Vector neighbors = new Vector();
	
	public LifeCell(boolean state) {
		setOpaque(true);
		setBorder(new LineBorder(borderColor, 1));
		setSize(10,10);
		this.state = state;
		draw();
		
		addMouseListener(new MouseAdapter() {		
			public void mousePressed(MouseEvent e)
			{
				//System.out.println("Clicked");
				((LifeCell)e.getComponent()).toggle();
			}
			public void mouseEntered(MouseEvent e) {
				//super.mouseEntered(e);
				
				/*
				 * Menu-item selections trigger mouse events in cells UNDER them
				 */
				if (e.getClickCount() > 0) return;
				if (e.getButton() == 1) return;
				
				if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) > 0) {
					/*
					System.out.println("Entered: Button down "+ e.isConsumed() 
							+ " : "+ e.getClass()
							+ " : "+ e.getModifiers()
							+ " : "+ e.paramString());
					*/
					((LifeCell)e.getComponent()).toggle();
				}
			}
		});
		
	}

	/**
	 * Set the state for this cell.
	 * Must be commit()d to have any effect. 
	 */
	public void setState(boolean newstate) {
		this.newstate = newstate;	
	}
	
	/**
	 * Commit the new state for this cell.
	 */
	public void commitState() {
		state = newstate;
		draw();
	}
	
	public void reset() {
		state = newstate = false;
		draw();
	}
	
	public boolean isAlive() {
		return state;
	}
		
	public void toggle() {
		setState(!isAlive());
		commitState();
	}
	
	public void draw() {
		if (state) {
			setBackground(aliveColor);
		}
		else {
			setBackground(deadColor);
		}
	}
	
	/**
	 * How many alive neighbors do i have?
	 */
	public int aliveNeighbors(int r) {
		int count = 0;
		for (int i=0; i < neighbors.size(); i++) {
			if (((LifeCell)neighbors.get(i)).state) {
				count++;
			}
		}
		//System.out.println("alive neighbors = "+ count);
		return count;
	}
	
	/**
	 * Ooh... new neighbor
	 */
	public void addNeighbor(LifeCell cell) {
		neighbors.add(cell);
	}
	
}