import java.io.*;
import java.util.*;

/**
 * A command-line application that can be used to calculate sales taxes
 * on different kinds of items.
 *
 * This application accepts one command-line argument, containing the
 * name of the output file. If the command-line argument is omitted,
 * this application will send all output to the console 
 * (i.e., standard output).
 *
 *
 * This work complies with the JMU Honor Code.
 *
 * @author Micheal Cottingham
 * @version 1.0 - 09/18/08
 */
public class TaxOnomy
{
    private static PrintStream    tape;
    private static Scanner        keyboard = new Scanner(System.in);

    // The arrays for category and price, respectively
	 private static int[] categoriesOfItems;
	 private static double[] pricesOfItems;

    // The number of items to add
	 private static int numItems;

    /**
     * The entry point of the application
     *
     * @param args The command-line arguments
     */
    public static void main(String args[])
    {
	    // tapeFile is defined as a file so that
		 // output can be stored in it
       File tapeFile;
		 // nonFoodOut, foodOut, preparedFoodOut
		 // These variables store their respective
		 // output
		 double nonFoodOut;
		 double foodOut;
		 double preparedFoodOut;

       // Set these to default to 0.00
       nonFoodOut = 0.00;
		 foodOut = 0.00;
		 preparedFoodOut = 0.00;

       // Code that handles the command-line arguments
       tape = null;

       // If there is a command-line argument, use it as the
       // file name (if possible)
       if ((args != null) && (args.length > 0))
       {
          tapeFile = new File(args[0]);
      
			 try
          {
             tape  = new PrintStream(tapeFile);
          }

          catch (IOException ioe)
          {
             tape  = System.out;          
          }
       }

       // Otherwise, use System.out
       else
       {
          tape = System.out;
       }

       // The application logic
		 // Request the number of items
		 // Through the requestInt method
		 numItems = requestInt("Enter the number of items: ");
		 System.out.println("You entered: " + numItems);

       // Set the size of the array
		 // for categories and prices
       categoriesOfItems = new int[numItems];
		 pricesOfItems = new double[numItems];

       // Loop through both category and prices
		 // to set their values
       for(int i = 0; i < numItems; i++)
		 {
		    categoriesOfItems[i] = requestCategory("Enter 0 for non-food, " +
			 		"1 for food, or 2 for prepared: ");
			 System.out.println("You entered: " + categoriesOfItems[i]);
			 pricesOfItems[i] = requestDouble("Enter the price: ");
			 System.out.println("You entered: " + pricesOfItems[i]);
       }

       // Calculate the taxes on each item
		 // by looping through
		 for(int i = 0; i < numItems; i++)
		 {
		    // Check if the item in question is Non food
			 // and use the appropriate method
		    if(categoriesOfItems[i] == TaxCalculator.NON_FOOD)
			 {
			    // Set the value of nonFoodOut to the latest value
				 // Not accumulate! :)
			    nonFoodOut = TaxCalculator.nonfoodTax(pricesOfItems, categoriesOfItems);
			 }

          // Check if the item in question is Food
			 // and use the appropriate method
          else if(categoriesOfItems[i] == TaxCalculator.FOOD)
			 {
			    // Set the value of foodOut to the latest value
				 // Not accumulate! :)
			    foodOut = TaxCalculator.foodTax(pricesOfItems, categoriesOfItems);
			 }

          // Check if the item in question is prepared food
			 // and use the appropriate method
          else if(categoriesOfItems[i] == TaxCalculator.PREPARED_FOOD)
			 {
			    preparedFoodOut = TaxCalculator.preparedfoodTax(pricesOfItems, categoriesOfItems);
			 }
		 }

       // Generate the required output
		 // tape is a variable, as per above
		 // that is set to either System.out or a filename
		 // depending on the user's input
		 tape.println("");
		 tape.printf("%10s\n", "  Summary");
		 tape.printf("%10s %4.4f\n", "Food: ", foodOut);
		 tape.printf("%10s %4.4f\n", "Prepared: ", preparedFoodOut);
		 tape.printf("%10s %4.4f\n", "Other: ", nonFoodOut);

       System.out.println("");
		 System.out.println("This program has ended normally.");
    } // end main

    /**
     * Prompt the user to enter a category and then
     * read it in (using the Scanner named keyboard).
     *
     * This method will/must continue to prompt the user
     * until she/he enters a valid category
     *
	  * @param prompt This is the output to show to the user
     * @return The value 
     */
    private static int requestCategory(String prompt)
    {
	    // category is the return value
       int category;
		 // value2 is a temporary holder
		 // for if the user enters an
		 // invalid entry
		 String value2;
		 // Check is used as a flag
		 boolean check;

       // Set the defaults
		 // Check is default to false
		 check = false;
		 // Category is default to -1
		 category = -1;

       // A do while loop so that the request for
		 // entry goes through at least once
		 // and while check is false, keep asking
		 do
		 {
		    // Prompt the user to input the number of items
			 System.out.print(prompt);

          // If the entry on the keyboard is indeed an
			 // int and a valid category, 
			 // save it and don't bother with the rest
			 if(keyboard.hasNextInt())
			 {
			    category = keyboard.nextInt();

             if(TaxCalculator.isValid(category))
				 {
				    check = true;
				 }
			 }

          // If the entry is not an integer
			 // set value2 to the entry, tell the user it is invalid
			 // and keep asking until a valid entry is given
          else
			 {
			 	  value2 = keyboard.next();
			     System.out.println("The input " + value2 + " is invalid");
			 }
		 } while(!check);

       return category;
    } // end requestCategory

    /**
     * Prompt the user to enter a double and then
     * read it in (using the Scanner named keyboard)
     *
     * @param prompt The custom portion of the prompt
     * @return The value 
     */
    private static double requestDouble(String prompt)
    {
	    // value is the return value for the method
       double value;
		 // value2 is a temporary placeholder, like the previous
		 // method
       String value2;
		 // As in the previous method, check is a flag
		 boolean check;

       // Set each variable to their defaults
		 check = false;
		 value = 0.0;

       // A do while loop so that the request for
		 // entry goes through at least once
		 // and while check is false, keep asking
		 do
		 {
		    // Prompt the user to input the number of items
			 System.out.print(prompt);

          // If the entry on the keyboard is indeed an
			 // double and a valid category, 
			 // save it and don't bother with the rest
			 if(keyboard.hasNextDouble())
			 {
      		    value = keyboard.nextDouble();
					 check = true;
		    }

          // Otherwise, report to the user
			 // that they entered something wrong
          else
			 {
			 	  value2 = keyboard.next();
			     System.out.println("The input " + value2 + " is invalid");
			 }
		 } while(!check);

       return value;
    } // end requestDouble

    /**
     * Prompt the user to enter an int and then
     * read it in (using the Scanner named keyboard)
     *
     * @param prompt The custom portion of the prompt
     * @return The value 
     */
    private static int requestInt(String prompt)
    {
	    // value is the return value
       int value;

		 // value2, as per the previous methods
		 // is a temporary holder for invalid
		 // values entered by the user
		 String value2;

       // check, as per the previous methods
		 // is a flag
		 boolean check;

       // Set each item to their default
		 check = false;
		 value = 0;

       // A do while loop so that the request for
		 // entry goes through at least once
		 // and while check is false, keep asking
		 do
		 {
		    // Prompt the user to input the number of items
			 System.out.print(prompt);

			 if(keyboard.hasNextInt())
			 {
      		    value = keyboard.nextInt();
					 check = true;
		    }

          else
			 {
			 	  value2 = keyboard.next();
			     System.out.println("The input " + value2 + " is invalid");
			 }
		 } while(!check);

       return value;
    } // end requestInt
} // end class