/* COP3330
 * AnimateThing project 4
 *
 * This class tests the Animal, Plant, and class of choice by students
 * The class of choice must be filled in where indicated with **
 *
 *HINTS (for Animal and Plant classes):
 *-Keep in mind the velocity for an animal can be negative (absolute value must be used to calculate loss of energy)
 */

import java.util.*;
import java.io.*;
 
 public final class AnimateThingTester {
 
 	//constants:
 	private final static Scanner stdin = new Scanner(System.in);//standard input scanner
 	private final static int NUMRANDOM = 10;//number of random things to have
 	private final static Random rGen = new Random();//random number generator
 	private final static String [] possibleNames = 
 				{"Animatio", "Thing", "Turing", "Godel", "Kleene", "Descartes", "Plato", "Aristotle", "Euclid", "Socrates", "Homer", "Mozart", "Bach", "Beethoven", "Mahler", "Strauss", "Stravinsky", "Ravel", "Brahms"};
 	private final static int MAXRESTORE = 8;//max amount of energy to restore each day
 	//animal parameters:
 	private final static String ANAME = "Animalia1";
 	private final static String ANAME2 = "Animalia12";
 	private final static int XVEL = 2;
 	private final static int YVEL = -1;
 	private final static int XVEL2 = -1;
 	private final static int YVEL2 = 3;
 	//plant parameters:
 	private final static String PNAME = "Plantasurus1";
 	private final static String PNAME2 = "Plantasurus2";
 	private final static int CHANGEH = 1;
 	private final static int CHANGEH2 = 3;
 	
 
 	public AnimateThingTester(){
 		//creates an object to test with
 	}
 	
 	public void testAnimal(){
 		//tests the Animal portion
 		System.out.println("Animal Test:\n----------------------\n");
 		
 		System.out.println(">>calling constructors for two Animals....");
 		Animal anim = new Animal(ANAME, XVEL, YVEL);
 		Animal anim2 = new Animal(ANAME2, XVEL2, YVEL2);
 		
 		System.out.println(">>Initial toString (" + ANAME+ " (alive), " + AnimateThing.INITIALENERGY + ", 0, 0)\n" + anim);
 		System.out.println(">>Initial toString (" + ANAME2 + " (alive), " + AnimateThing.INITIALENERGY + ", 0, 0)\n" + anim2);
 	}
 	
 	public void testPlant(){
 		//tests the Plant portion of the assignment
 		System.out.println("Plant Test:\n----------------------\n");
 		
 		System.out.println(">>calling constructors for two Plants....");
 		Plant pl1 = new Plant(PNAME, CHANGEH);
 		Plant pl2 = new Plant(PNAME2, CHANGEH2);
 		
 		System.out.println(">>Initial toString (" + PNAME+ " (alive), " + AnimateThing.INITIALENERGY + ", 0)\n" + pl1);
 		System.out.println(">>Initial toString (" + PNAME2 + " (alive), " + AnimateThing.INITIALENERGY + ", 0)\n" + pl2);
 	}
 	
 	public void testChoice(){
 		//tests the choice portion of the assignment
 		 System.out.println("<Choice> Test:\n----------------------\n");
 		
 		System.out.println(">>calling constructors for two <Choice>s....");
 		/**Change This **/
 		Animal choice = new Animal("choice", 1, 1);
 		Animal choice2 = new Animal("choice2", 1, 1);
 		/****************/
 		
 		System.out.println(">>Initial toString (should still indicate a name and alive\n" + choice);
 		System.out.println(">>Initial toString (should still indicate a name and alive)\n" + choice2);
 	}
 	
	public void live(){
		//loops through calling days, printing output after each.
		
		//start with setting up our life:
		//required animatethings: (should always live and die at same time)
		Animal anim = new Animal(ANAME, XVEL, YVEL);
 		Animal anim2 = new Animal(ANAME2, XVEL2, YVEL2);
		Plant pl1 = new Plant(PNAME, CHANGEH);
 		Plant pl2 = new Plant(PNAME2, CHANGEH2);
 		
 		/**Change This **/
 		Animal choice = new Animal("choice", 1, 1);
 		/****************/
		
		//some randomly created life:
		AnimateThing []things = new AnimateThing[NUMRANDOM + 5];
		things[0] = anim;
		things[1] = anim2;
		things[2] = pl1;
		things[3] = pl2;
		things[4] = choice;
		for (int i = 5; i < things.length; i++){
			double choose = rGen.nextDouble() * 2.0;//figure out which to choose
			AnimateThing newThing;
			if (choose > 1)
				newThing = new Plant(randomName(), rGen.nextInt(7));
			else
				newThing = new Animal(randomName(), (2 - rGen.nextInt(7)), (2 - rGen.nextInt(7)));
			things[i] = newThing;
		}
		
		//THE DAILY LOOP:
		boolean keepLiving = true;
		int day = 0;
		final int alwaysRestore = 4;
		final boolean randomRestore = false;//change to true to make more life-like, but inconsistent
		while (keepLiving){
			
			int numAlive = 0;//keeps track of the number of things alive
			
			for (AnimateThing at: things){
				//run the daily life for each thing
				if (at.isAlive()){
					//figure out amount of energy to restore
					int restore = alwaysRestore;//energy to restore
					if (randomRestore)
						restore = rGen.nextInt(MAXRESTORE);
					at.day(restore);
					numAlive++;
				}
			}
			
			//print statistics:
			day++;
			System.out.println("\n------------------------------------------\nDAY: " + day + " (things alive: " + numAlive + ")");
			for (int i = 0; i < things.length; i++){
				System.out.println(" Thing "+ i + ":");
				if (things[i].isAlive())
					System.out.println("  " + things[i]);//calls the toString
				else
					System.out.println("  " + things[i].getName() + " is no longer alive.\n");
			}
			
			//determine whether to go on
			System.out.print("Press Enter to continue (q + Enter to quit):");
			String quit = stdin.nextLine();
			if ((quit.equals("q")) || (quit.equals("Q"))){
				keepLiving = false;
			}
		}
		
		//print things at end:
		System.out.println("\nList of Things:");
		for (int i = 0; i < things.length; i++){
			System.out.println(" Thing "+ i + ":");
			System.out.println("  " + things[i]);//calls the toString
		}
		
	} 	
	
 	////////////////////////////////////////////////////
 	//static /  main
 	public static void main (String [] args){
 		//main to call tests:
 		AnimateThingTester att = new AnimateThingTester();
 		
 		waitKey("perform Animal constructor / toString test");
 		att.testAnimal();
 		waitKey("perform Plant constructor / toString test");
 		att.testPlant();
 		waitKey("perform <Choice> constructor / toString test");
 		att.testChoice();
 		
 		//calls a method which puts program in loop to live day by day
 		waitKey("start the simulation of multiple days..test.");
 		att.live();
 	}
 	
 	public static void waitKey(String toBegin){
 		//waits for a key to be pressed
 		System.out.println("Press Enter to " + toBegin);
 		stdin.nextLine();
 	}
 	
 	public static String randomName(){
 		//returns a chosen "randomly" from the list of possible names
 		return possibleNames[rGen.nextInt(possibleNames.length)];
 	}
 }
