import java.awt.Color;
import java.util.Enumeration;

public abstract class Human extends RandomWalker {
	// OVERVIEW: Human is a datatype which walks around the grid, randomly
	// taking one turn for every step.  When taking a turn, a Human can age,
	// mate, produce offspring, or die.  Each turn represents the aging period
	// of four years.  A human can only reproduce in the adult stage with members
	// of the opposite sex.  A Human is a child for five turns, an adult ages for
	// ten turns, and a senior ages for five turns and then dies.
	
	
	
	protected boolean inTurn;
	protected Human child;
	protected boolean isAlive;
	protected int genderM = 0;
	protected int genderF = 1;
	protected int genderNull = 2;
	protected boolean isMating = false;
	int age = 0;
	int gender = 0;
	protected int firstIndex = 0;

	public Human() {
		this(1);
	}

	public Human(int ageH) {
		inTurn = false;
		isAlive = true;

	}

	public abstract Color getNaturalColor();
	public abstract int getGender();

	protected Color natural = this.getNaturalColor();

	public Color getColor()
	//Effects: Gets the color for the simulation of the object depending on the
	//natural color of the object and its current action.
	{

		return getNaturalColor();

	} //@nowarn NonNullResult // ESC/Java doesn't know Color constants are not null

	public void executeTurn() throws RuntimeException
	// Note: requires isInitialized is inherited from SimObject
	// EFFECTS: First, checks if 'this' has neighbor.  If it does, calls getGender()
	// on the neighbor.  If the neighbor is of opposite gender and is an adult, this 
	// and neighbor mate. This and neighbor then produce a child of random gender if
	// this has an adjacent empty location to place the child.
	// Else picks a random direction and tries to move that way
	{

		if (!isAlive) {
			return;
		}

		inTurn = true;

		synchronized (getGrid()) {

			if (this.age > 21) {
				Grid a = getGrid();

				a.removeObjectAt(getX(), getY());

				isAlive = false;
				return;
			}
			super.executeTurn();

			Enumeration neighbors = getNeighbors();

			while (neighbors.hasMoreElements()) {
				Human neighbor = (Human) neighbors.nextElement();

				if ((this.getGender() != neighbor.getGender())
					&& (neighbor.getGender() != 2)) {

					if ((this.age > 5)
						&& (neighbor.age) > 5
						&& (this.age < 16)
						&& (neighbor.age < 16)) {

						Enumeration childLoc = this.getFreeLocations();

						if (childLoc.hasMoreElements()) {

							System.out.println("Makin' Babies!");
							Coordinate childLocation =
								(Coordinate) childLoc.nextElement();

							gender = GenRandom.nextInt(2);

							if (gender == genderM) {
								child = new Male();
							} else if (gender == genderF) {
								child = new Female();
							} else {
								System.err.println("Random Number error!");
								return;
							}

							child.init(
								childLocation.getX(),
								childLocation.getY(),
								grid);

							try {
								grid.setObjectAt(
									childLocation.getX(),
									childLocation.getY(),
									child);
								child.resumeObject();
								//System.err.println("Created child: " + child);
							} catch (BadLocationException ble) {
								// This should never happen
								System.err.println(
									"Bad location: "
										+ childLocation.getX()
										+ ", "
										+ childLocation.getY());
								System.exit(-1);
							}
							

							neighbor.age++;
						}

					} else {
						System.out.println("Pardon me");
					}

				} else {

					System.out.println("Hello!");

				}
				delay(25);

				//@assume neighbor != null
				//no null neighbors in graph;

			}

		}
		this.age++;

		inTurn = false;
	}

	public void setHumanAge(int ageH) {
		age = ageH;
		
	}
}