package simulator;

/*
 * AmusementParkSimulation.java
 * Created on Oct 31, 2005
 *
 */

import java.util.Collection;
import java.util.Scanner;
import java.io.FileNotFoundException;
import java.lang.Thread;

/**
 *  AmusementParkSimulation - This class contains methods which start off the program, displaying the main menu
 *  and running simulations.
 *
 *  @author Gabriela
 *
 */
public class AmusementParkSimulation
{
	public static AmusementPark park;
	
	// These collections hold the data read in from files.
	private Collection<Customer> customers;
	private Collection<Attraction> attractions;
	
	
	public AmusementParkSimulation() 
	{
	}
	
	private Scanner scanner = new Scanner(System.in);
	private boolean simRanOnce = false;
	
	/**
	 * Used to control the pause between an error message and return to the display of the 
	 * last menu or question, for clarity and flow of the program.
	 *
	 */
	public static void pause()
	{
		try
		{
			Thread.sleep(500);
		}
		catch(InterruptedException e){}
	}
	
	/**
	 * Displays error messages using the information passed when it is called, to provide specific 
	 * information about each error, while keeping the messages consistent.
	 * 
	 * @param displayMessage
	 */
	public static void errorMessage(String displayMessage)
	{
		System.err.println("* Invalid " + displayMessage + "\n* Please try again\n");
		pause();
	}
	
	
	/**
	 * Runs the simulation, displaying visual feedback on its progress.
	 *
	 */
	private void runSimulation()
	{
		System.out.println("\nRunning Simulation");

		// open the park
		park.openPark(customers);

		// run through the simulation
		boolean keepSimulating = true;

		int numClockTicks = 0;

		while(keepSimulating)
		{
			keepSimulating = park.onClockTick();

			numClockTicks++;

			if((numClockTicks % 50) == 0)
				//System.out.print(".");
				System.out.print(">");
			if((numClockTicks % 100) == 0)
				//System.out.print(".");
				System.out.print(">");
			if((numClockTicks % 150) == 0)
				//System.out.print(".");
				System.out.print(">");

			try
			{
				Thread.sleep(1);
			}
			catch(InterruptedException e){}
		}

		System.out.println("\nSimulation Complete\n");
	}
	
	
	/**
	 * Prompts user for a filename of type fileType, either attraction or customer, and retrieves data
	 * from the file.
	 * 
	 * @param fileType - either "attractions" or "customers"
	 */
	private void retrieveFromFile(String fileType)
	{	
		System.out.println("Please enter " + fileType + " file name.");
		String filename = scanner.nextLine();
		
		// Make sure that a proper filename is entered, ending in .txt
		if(!filename.endsWith(".txt") || filename.length() < 5)
		{
			errorMessage("file name: must be a name ending in .txt");
			retrieveFromFile(fileType);
			return;
		}
	
		// Read in all of the attractions from the file, if it is an attractions file
		if(fileType.equals("attractions"))
		{
			AttractionReader attractionReader = new AttractionReader();
	
			try
			{
				attractions = attractionReader.readAttractions(filename);
			}
			catch(FileNotFoundException e)
			{
				errorMessage("file name: file not found");
				retrieveFromFile(fileType);
				return;
			}
		}
		
		// Read in all of the customers from the file, if it is a customers file
		else if(fileType.equals("customers"))
		{
			CustomerReader customerReader = new CustomerReader();
			try
			{
				customers = customerReader.readCustomers(filename);
			}
			catch(FileNotFoundException e)
			{
				errorMessage("file name: file not found");
				retrieveFromFile(fileType);
				return;
			}
			catch(CustomerReadException e)
			{
				errorMessage(e.getMessage());
				retrieveFromFile(fileType);
				return;
			}
		}
	}
		
	
	/**
	 * Runs a simulation by calling runSimulation, asking the user for confirmation if a simulation 
	 * has already been run, since a new simulation overwrites any old statistics.
	 *
	 */
	private void newSimulation()
	{
		if(simRanOnce)
		{
			// The simulation has been already 
			System.out.println("All current simulation statistics will be lost.\n" +
					"Are you sure you would like to run a new simulation? (y/n)");
			String response = scanner.nextLine();

			if(response.length() < 1 || response.length() > 1)
			{
				errorMessage("input: must be a character");					
				newSimulation();
				return;
			}

			else
			{
				char command = response.charAt(0);

				switch(command)
				{
					case 'n':
					{
						mainMenu();
						return;
					}

					case 'y':
					{
						break;
					}
					
					default:
					{
						errorMessage("command : must be y or n");

						newSimulation();
						return;
					}
				}
			}
		}
		
		Logger fileLogger = new FileLogger();
		Location entrance = new Location(0, 0);
		Location exit = new Location(0, 0);
		Time openingTime = new Time(9, 0);
		Time closingTime = new Time(21, 0);
		
		retrieveFromFile("attractions");
		
		park = new AmusementPark(attractions, entrance, exit, openingTime,
				closingTime, fileLogger);
		
		retrieveFromFile("customers");
					
		

		simRanOnce = true;
		
		runSimulation();
	}

	
	/**
	  *  Handles the main menu, including calls to all the submenus and running
	  *  running new simulations.
	  */
	public void mainMenu()
	{
		System.out.println("\nMain Menu:  What would you like to do?\n");
	
		System.out.println("[c] View customer stats");
		System.out.println("[a] View attraction stats");
		System.out.println("[r] Run new simulation");
		System.out.println("[e] Exit\n");
	
		String response = scanner.nextLine();
	
		if(response.length() < 1 || response.length() > 1)
		{
			errorMessage("input: must be a character");
			mainMenu();
		}
	
		else
		{
			char command = response.charAt(0);
	
			switch(command)
			{
				case 'c':
				{
					if(!simRanOnce)
					{
						errorMessage("command: there is no customer data because simulation has not been run");
						mainMenu();
					}
					
					else
					{
						CustomerStats customerStats = new CustomerStats(park);
						customerStats.customerStatsMenu();
						mainMenu();
					}
					
					break;
				}
	
				case 'a':
				{
					if(!simRanOnce)
					{
						errorMessage("command: there is no attraction data because simulation has not been run");
						mainMenu();
					}
					
					else
					{
						AttractionStats attractionStats = new AttractionStats(park);
						attractionStats.attractionStatsMenu();
						mainMenu();
					}
					
					break;
				}
	
				case 'r':
				{
					newSimulation();
					mainMenu();
					break;
				}
	
				case 'e':
				{
					System.out.println("\nThank You. Goodbye.");
					return;
				}
	
				default:
				{
					errorMessage("command: must be one of the menu commands");
					mainMenu();
					break;
				}
			}
		}
	}
}
