package simulator;

import java.io.FileWriter;
import java.io.IOException;
import java.util.Iterator;
import java.util.Scanner;

/**
 * AttractionStats - This class handles the attraction 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 AttractionStats {
    private AmusementPark park;

    private Iterator<Attraction> attractions;

    private Scanner scanner = new Scanner(System.in);

    public AttractionStats(AmusementPark park) {
        this.park = park;
        attractions = park.getAllRides();
    }

    /**
     * Prints to the screen the statistics of the attraction which was visited
     * by the most customers.
     * 
     */
    private void printAttractionWithMostCustomers() {

        attractions = park.getAllRides();

        if (!attractions.hasNext())
        {
        	return;
        }
        
        Attraction attractionWithMostCustomers = attractions.next();
        int mostCustomers = attractionWithMostCustomers.getTotalRiders();

        while (attractions.hasNext()) {
            Attraction a = attractions.next();

            if (a.getTotalRiders() > mostCustomers) {
                attractionWithMostCustomers = a;
                mostCustomers = a.getTotalRiders();
            }
        }

        attractionWithMostCustomers.printStats();
    }

    /**
     * Prints to the screen the statistics of the attraction which was visited
     * by the least customers.
     * 
     */
    private void printAttractionWithLeastCustomers() {
        attractions = park.getAllRides();

        if (!attractions.hasNext())
        {
        	return;
        }
        
        Attraction attractionWithLeastCustomers = attractions.next();
        int leastCustomers = attractionWithLeastCustomers.getTotalRiders();

        while (attractions.hasNext()) {
        	Attraction a = attractions.next();

            if (a.getTotalRiders() < leastCustomers) {
                attractionWithLeastCustomers = a;
                leastCustomers = a.getTotalRiders();
            }
        }

        attractionWithLeastCustomers.printStats();
    }

    /**
     * Prints to the screen the statistics of the attraction which had the
     * highest average wait time for customers in its line.
     * 
     */
    private void printAttractionWithHighestAvgWait() {
        attractions = park.getAllRides();

        if (!attractions.hasNext())
        {
        	return;
        }
        
        Attraction attractionWithHighestAvgWait = attractions.next();
        double highestAvgWait = attractionWithHighestAvgWait.getAvgWaitingTime();

        while (attractions.hasNext()) {
            Attraction a = attractions.next();

            if (a.getAvgWaitingTime() > highestAvgWait) {
                attractionWithHighestAvgWait = a;
                highestAvgWait = a.getAvgWaitingTime();
            }
        }

        attractionWithHighestAvgWait.printStats();
    }

    /**
     * Prints to the screen the statistics of the attraction which had the
     * lowest average wait time for customers in its line.
     * 
     */
    private void printAttractionWithLowestAvgWait() {
        attractions = park.getAllRides();

        if (!attractions.hasNext())
        {
        	return;
        }
        
        Attraction attractionWithLowestAvgWait = attractions.next();
        double lowestAvgWait = attractionWithLowestAvgWait.getAvgWaitingTime();

        while (attractions.hasNext()) {
            Attraction a = attractions.next();

            if (a.getAvgWaitingTime() < lowestAvgWait) {
                attractionWithLowestAvgWait = a;
                lowestAvgWait = a.getAvgWaitingTime();
            }
        }

        attractionWithLowestAvgWait.printStats();
    }

    /**
     * Searches for an attraction by name, using a name entered by the user. If
     * the attraction with a matching name is found, its statistics are printed.
     * If no attraction 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 attractionSearch() {
        System.out
                .println("Please enter attraction name, or 'm' to return to menu.");
        String name = scanner.nextLine();

        if (name.equals("m")) {
            return;
        }

        else {
        	attractions = park.getAllRides(); 
            while (attractions.hasNext()) {
            	Attraction a = attractions.next();

            	if (a.getName().equals(name)) {
                    a.printStats();
                    AmusementParkSimulation.pause();
                    return;
                }
            }

            System.out.println("Attraction " + name + " not found.\n");
            AmusementParkSimulation.pause();
            attractionSearch();
        }
    }

    /**
     * Writes the statistics of all of the attractions to a file according to a
     * filename input by the user.
     * 
     */
    private void writeAttractionStatsToFile() {
        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");
            writeAttractionStatsToFile();
        }

        else {
            try {
                FileWriter outfile = new FileWriter(filename);

                Iterator<Attraction> ridesDone = park.getAllRides();

                while (ridesDone.hasNext()) {
                    Attraction a = ridesDone.next();
                    a.writeStatsToFile(outfile);
                }

                outfile.close();

                System.out
                        .println("\nAttraction stats have been written to file \""
                                + filename + "\".");
                System.out.println("Press Enter to continue.");

                scanner.nextLine();
            } catch (IOException e) {
            }
        }
    }

    /**
     * Handles the attraction statistics menu, and all of the ways the
     * attraction statistics can be viewed. This includes viewing single notable
     * attractions, searching through all attractions, and writing all of the
     * attraction statistics to a file.
     * 
     */
    public void attractionStatsMenu() {
        // Overall statistics printed before the menu to give user an idea of
        // the
        // statistics before choosing to look at any specifics.
        System.out.println("\nAttraction 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 attraction, view all of
        // the attractions,
        // or write all of the attractions to a file
        System.out
                .println("\nAttraction Statistics Menu:  How would you like to view the stats?\n");

        System.out.println("By Attraction:");
        System.out.println("[a] Most customers.");
        System.out.println("[b] Least customers.");
        System.out.println("[c] Longest average wait time.");
        System.out.println("[d] Shortest average wait time.\n");

        System.out.println("[s] Search by attraction name.");
        System.out.println("[w] Write all attraction 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");
            attractionStatsMenu();
        }

        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': {
                printAttractionWithMostCustomers();

                System.out.println("Press Enter to continue.");
                scanner.nextLine();

                attractionStatsMenu();
                break;
            }

            case 'b': {
                printAttractionWithLeastCustomers();

                System.out.println("Press Enter to continue.");
                scanner.nextLine();

                attractionStatsMenu();
                break;
            }

            case 'c': {
                printAttractionWithHighestAvgWait();

                System.out.println("Press Enter to continue.");
                scanner.nextLine();

                attractionStatsMenu();
                break;
            }

            case 'd': {
                printAttractionWithLowestAvgWait();

                System.out.println("Press Enter to continue.");
                scanner.nextLine();

                attractionStatsMenu();
                break;
            }

            case 's': {
                attractionSearch();

                System.out.println("Press Enter to continue.");
                scanner.nextLine();

                attractionStatsMenu();
                break;
            }

            case 'w': {
                writeAttractionStatsToFile();

                attractionStatsMenu();
                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");
                attractionStatsMenu();
                break;
            }
            }
        }
    }
}
