package simulator;

import java.io.FileWriter;
import java.io.IOException;
import java.util.Iterator;
import java.util.Scanner;

/**
 * CustomerStats - This class handles the customer statistics menu and the implementation of
 * each of its options, including printing the statistics, searching through them, and writing them
 * to a file.
 * 
 * @author Gabriela Marcu
 *
 */
public class CustomerStats 
{
	private AmusementPark park;
	private Iterator<Customer> customersDone;
	
	private Scanner scanner = new Scanner(System.in);
	
	public CustomerStats(AmusementPark park)
	{
		this.park = park;
	}
	
	
	/**
	 * Prints to the screen the statistics of the customer who spent the most
	 * time in the park.
	 *
	 */
	private void printCustomerWithMostTimeInPark()
	{
		customersDone = park.getAllFinishedCustomers();

		if (!customersDone.hasNext())
		{
			return;
		}
		
		Customer customerWithMostTimeInPark = customersDone.next();
		int mostTimeInPark = customerWithMostTimeInPark.getTotalTimeInPark();

		while(customersDone.hasNext())
		{
			Customer c = customersDone.next();

			if(c.getTotalTimeInPark() > mostTimeInPark)
			{
				customerWithMostTimeInPark = c;
				mostTimeInPark = c.getTotalTimeInPark();
			}
		}

		customerWithMostTimeInPark.printStats();
	}

	
	/**
	 * Prints to the screen the statistics of the customer who spent the least
	 * time in the park.
	 *
	 */
	private void printCustomerWithLeastTimeInPark()
	{
		customersDone = park.getAllFinishedCustomers();

		if (!customersDone.hasNext())
		{
			return;
		}
		
		Customer customerWithLeastTimeInPark = customersDone.next();
		int leastTimeInPark = customerWithLeastTimeInPark.getTotalTimeInPark();

		while(customersDone.hasNext())
		{
			Customer c = customersDone.next();

			if(c.getTotalTimeInPark() < leastTimeInPark)
			{
				customerWithLeastTimeInPark = c;
				leastTimeInPark = c.getTotalTimeInPark();
			}
		}

		customerWithLeastTimeInPark.printStats();
	}

	
	/**
	 * Prints to the screen the statistics of the customer who spent the most
	 * time in line.
	 *
	 */
	private void printCustomerWithMostTimeInLine()
	{
		customersDone = park.getAllFinishedCustomers();

		if (!customersDone.hasNext())
		{
			return;
		}
		
		Customer customerWithMostTimeInLine = customersDone.next();
		int mostTimeInLine = customerWithMostTimeInLine.getTotalTimeInLine();

		while(customersDone.hasNext())
		{
			Customer c = customersDone.next();

			if(c.getTotalTimeInLine() > mostTimeInLine)
			{
				customerWithMostTimeInLine = c;
				mostTimeInLine = c.getTotalTimeInLine();
			}
		}

		customerWithMostTimeInLine.printStats();
	}

	
	/**
	 * Prints to the screen the statistics of the customer who spent the least
	 * time in line.
	 *
	 */
	private void printCustomerWithLeastTimeInLine()
	{
		customersDone = park.getAllFinishedCustomers();

		if (!customersDone.hasNext())
		{
			return;
		}
		
		Customer customerWithLeastTimeInLine = customersDone.next();
		int leastTimeInLine = customerWithLeastTimeInLine.getTotalTimeInLine();

		while(customersDone.hasNext())
		{
			Customer c = customersDone.next();

			if(c.getTotalTimeInLine() < leastTimeInLine)
			{
				customerWithLeastTimeInLine = c;
				leastTimeInLine = c.getTotalTimeInLine();
			}
		}

		customerWithLeastTimeInLine.printStats();
	}

	
	/**
	 * Searches for a customer by name, using a name entered by the user. If the 
	 * customer with a matching name is found, its statistics are printed. If no
	 * customer is found with the given name, a message is printed and the search is 
	 * started again with the prompt for the user to enter a name to search for.
	 *
	 */
	private void customerSearch()
	{
		System.out.println("Please enter customer name, or 'm' to return to menu.");
		String name = scanner.nextLine();
		
		if(name.equals("m"))
		{
			return;
		}
		
		else
		{
			customersDone = park.getAllFinishedCustomers();
			
			boolean customerFound = false;
			
			while(customersDone.hasNext())
			{
				Customer c = customersDone.next();
				if(c.getName().equals(name))
				{
					c.printStats();
					AmusementParkSimulation.pause();
					customerFound = true;
				}
			}
			
			if(!customerFound)
			{
				System.out.println("Customer " + name + " not found.\n");
				AmusementParkSimulation.pause();
				customerSearch();
			}
		}
	}

	
	/**
	 * Writes the statistics of all of the customers to a file according to a filename
	 * input by the user.
	 *
	 */
	private void writeCustomerStatsToFile()
	{
		System.out.println("Please enter destination filename.");
		String filename = scanner.nextLine();

		if(!filename.endsWith(".txt"))
		{
			AmusementParkSimulation.errorMessage("input:  must be a name ending in .txt");
			writeCustomerStatsToFile();
		}

		else
		{
			try
			{
				FileWriter outfile = new FileWriter(filename);

				customersDone = park.getAllFinishedCustomers();

				while(customersDone.hasNext())
				{
					Customer c = customersDone.next();
					c.writeStatsToFile(outfile);
				}

				outfile.close();

				System.out.println("\nCustomer stats have been written to file \"" + filename + "\".");
				System.out.println("Press Enter to continue.");

				scanner.nextLine();
				return;
			}
			catch(IOException e){}
		}
	}

	
	/**
	 * Handles the customer statistics menu, and all of the ways the customer statistics
	 * can be viewed. This includes viewing single notable customers, searching through
	 * all customers, and writing all of the customer statistics to a file.
	 *
	 */
	public void customerStatsMenu()
	{
		// Overall statistics printed before the menu to give user an idea of the
		// statistics before choosing to look at any specifics.
		System.out.println("\nCustomer Statistics Overview:");
		System.out.println("Stat 1");
		System.out.println("Stat 2");
		System.out.println("Stat 3");

		// Menu containing the options to view a single customer, view all of the customers,
		// or write all of the customers to a file
		System.out.println("\nCustomer Statistics Menu: How would you like to view the stats?\n");

		System.out.println("By Customer:");
		System.out.println("[a] Most time in park.");
		System.out.println("[b] Least time in park.");
		System.out.println("[c] Most time in line.");
		System.out.println("[d] Least time in line.\n");
		
		System.out.println("[s] Search by customer name.");
		System.out.println("[w] Write all customer stats to file.\n");
				
		System.out.println("[m] Return to Main Menu.\n");
		
		// Store the user input
		String response = scanner.nextLine();
		
		// Make sure the input response is valid		
		if(response.length() < 1 || response.length() > 1)
		{
			AmusementParkSimulation.errorMessage("input: must be a character");
			customerStatsMenu();
		}

		else
		{
			// Convert the command, which was read in as a string, into a char to be 
			// used for the switch statement.
			char command = response.charAt(0);

			switch(command)
			{
				case 'a':
				{
					printCustomerWithMostTimeInPark();

					System.out.println("Press Enter to continue.");
					scanner.nextLine();
					
					customerStatsMenu();
					break;
				}

				case 'b':
				{
					printCustomerWithLeastTimeInPark();

					System.out.println("Press Enter to continue.");
					scanner.nextLine();
					
					customerStatsMenu();
					break;
				}

				case 'c':
				{
					printCustomerWithMostTimeInLine();

					System.out.println("Press Enter to continue.");
					scanner.nextLine();					
					
					customerStatsMenu();
					break;
				}

				case 'd':
				{
					printCustomerWithLeastTimeInLine();

					System.out.println("Press Enter to continue.");
					scanner.nextLine();
					
					customerStatsMenu();
					break;
				}

				case 's':
				{
					customerSearch();

					System.out.println("Press Enter to continue.");
					scanner.nextLine();
					
					customerStatsMenu();
					break;
				}

				case 'w':
				{
					writeCustomerStatsToFile();

					customerStatsMenu();
					break;
				}

				case 'm':
				{
					return;
				}

				// Command invalid because it does not match any of these, so
				// user must try again and enter a new command.
				default:
				{
					AmusementParkSimulation.errorMessage("command: must be one of the menu commands");
					customerStatsMenu();
					break;
				}
			}
		}
	}
}
