
//imported for use with PrintStream object
import java.io.*;
//imported for use with input
import java.text.DecimalFormat;
import java.util.InputMismatchException;
import java.util.Scanner;

/**
 * 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  Jeremy Halterman
 * @version 1.1
 * @date 9-16-08
 */

//publicly avaialable class
public class TaxOnomyZ
{
	//private to this class - a PrintStream object that mimmicks a buffer
	//is the Class that offers println methods, etc
    private static PrintStream    tape;
    //Scanner object used to receive input from user's
    private static Scanner        keyboard = new Scanner(System.in);

    /**
     * The entry point of the application
     *
     * @param args   The command-line arguments
     */
    public static void main(String[] args)
    {
        //creates a File object that is used to hold a file, etc specified by user
    	File           tapeFile;       
       
       //string for holding user input
       String userInput;
       
       //a variable declared to hold user's input for number of items
       int itemLoop;
       
       double bill;
       bill = 0.0;
       //input prompts
       System.out.println("Enter the number of items: ");
       
       /*takes the keyboard input after a carriage return is issued by user and
        *tests it for an integer value*/
       while(!keyboard.hasNextInt())
       {
    	   //repeats until the proper input is done by user
    	   System.out.println("Enter the number of items: ");
    	   keyboard.nextLine();
       }//end while
       
       //proper user input is read from keyboard into a userInput string
       userInput = keyboard.nextLine();
       
       //this variable holds the converted String's value as an integer
       itemLoop = Integer.parseInt(userInput);
       
       //arrays created for user's needs
       double[] itemPrices;
       int[] categChoices;
       
       //arrays initialized with a size
       itemPrices = new double[itemLoop];
       categChoices = new int[itemLoop];
       
            //loop for taking in user's inputs--controlled by arrays max value
       		for(int i = 0; i<itemLoop; i++)
       		{
       			/*gives each categChoices element a category value
       			 *as specified by the requestCategory method*/
       			categChoices[i] = requestCategory();
       
       			//prompts user outside of requestDouble method for price
       			System.out.println("Enter the price: ");
       			//String holding keyboard value
       			userInput = keyboard.nextLine();
       			//the array holds each userInput returned from the requestDouble method
       			itemPrices[i] = requestDouble(userInput);
       		}//end for loop
       
       // Code that handles the command-line arguments
       //initializes the tape value to null
       tape = null;

       // If there is a command-line argument, use it as the
       // file name (if possible)
       if ((args != null) && (args.length > 0))
       {
    	  //used by program at command line for passing files to program input
          tapeFile = new File(args[0]);
          
          /*a try block used to attempt to assign the PrintStream method
           *a command line entered filename*/
          try
          {
             tape  = new PrintStream(tapeFile);
          }//end try
          
          //if not found throws an io exception
          
          catch (IOException ioe)
          {
        	 /*bypasses the case that a user enters an incorrect file or enters
        	   no file at all-- handled by applying the .out object from the 
        	   System class to the value*/
             tape  = System.out;          
          }//end catch
       }//end if
       
       // Otherwise, use System.out
       else
       {
    	   /*assigns the .out object from the 
    	   System class to the value tape*/
          tape = System.out;          
       }//end else
       
       //Decimal for printing out total cost
       DecimalFormat formatter = new DecimalFormat("#0.00");
       
       // The application logic
       // Generate the required output
       /*uses the PrintStream value 'tape' ---if user inputs file then
        *reads from the file, else the tape assumes the value of the System.out
        *class and object*/
       
       /*each line is formatted with 10 space width for field and
        *8 width for numerical values with a 4 decimal float limit*/
       tape.println();
       tape.printf("%10s " + "\n","Tax summary");
       tape.printf("%10s %8.4f\n","Food: ",
    		   (float)TaxCalculatorZ.foodTax(itemPrices, categChoices));
       tape.printf("%10s %8.4f\n","Prepared: ",
    		   (float)TaxCalculatorZ.preparedfoodTax(itemPrices, categChoices));
       tape.printf("%10s %8.4f\n","Other: ",
    		   (float)TaxCalculatorZ.nonfoodTax(itemPrices, categChoices));
       
       tape.println();
       
       /*loop for cycling through the total method and receiving cost and tax
        *of each*/
       for(int categoryToInclude = 0; categoryToInclude <3; categoryToInclude++)
       {
       //lists the number of each category along with cost of items
       tape.printf("%6s %2s %8.4f\n","Total for: ", categoryToInclude,
    		   (float)TaxCalculatorZ.total(itemPrices, categChoices,
    				   categoryToInclude));
       
       //uses a double to store the looping totals of each category
       bill += TaxCalculatorZ.total(itemPrices, categChoices,
			   categoryToInclude);
       }
       
       //prints out the total cost 
       tape.printf("Total bill:   $" + formatter.format(bill));
       tape.println();
       //informs execution
       tape.println("The 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
     *
     * @return category        The value 
     */
    private static int requestCategory()
    {
       //declared and initialized variable for receiving each item's type
       int        category = 0;
       
       //variable for holding a temporary input
       int userChoice = 0;
       //loop control
       boolean done = true;
		
       //loop that attempts to receive a value from the user
       do
		{
    	    //used try-catch for input of category, hoping for appropriate integer
			try
			{
				System.out.println("Enter 0 for non-food, 1 for food, or " +
	       		" 2 for prepared: ");
				//receives user input
				userChoice = keyboard.nextInt();
				keyboard.nextLine();
				
				//stops loop at the while portion
				done = false;
				
				//tests user input choices and assigns appropriate values
				if(userChoice == 0)
			       	category = 0;
			       
			      	else if(userChoice == 1)
			      	category = 1;
			     
			      		else if(userChoice == 2)
			      		category = 2;
				
			}//end try block
			
			//catches an exception of the wrong input type
			catch(InputMismatchException ime)
			{
			//used to hold the character that is wrong in the buffer
		    //and discards it
			keyboard.nextLine();
			System.out.println("Please enter 0 for non-food, 1 for food, or " +
       		" 2 for prepared: ");
			}//end catch
		
		//ends while loop
		}while(done);
        
       //echoes user's input
       System.out.println("You chose category: " + category);
       
        /*returns a value 0-2 to be assigned to categChoices array and
         *eventually passed to each TaxCalculator method*/
       	return category;
    }//end requestCategory method




    /**
     * 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 value       The value 
     */
    private static double requestDouble(String prompt)
    {
       //local variable for holding price
       double       value;
       value = 0.0;//initialized to 0
       
       //no prompt is issued, instead user is asked by main method for value
       value = Double.parseDouble(prompt);
       //echoes user input
       System.out.println("You entered :" + value);
       /*returns a value to be assigned to itemPrices array and
        *eventually passed to each TaxCalculator method*/
       return value;
    }//end requestDouble method



    /**
     * 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)
//    {
//       int          value;
//       value = 0;
//       
//       String userInput;
//       
//       System.out.println("Enter the price: ");
//       
//       
//       while(!keyboard.hasNextInt())
//       {
//    	   System.out.println("Enter the price: ");
//       userInput = keyboard.nextLine();
//       }
//       
//       userInput = keyboard.nextLine();
//       //consume remaining carriage return
//       keyboard.nextLine();
//       value = Integer.parseInt(userInput);
//
//
//       return value;
//    }

    
}//end TaxOnomy Class
