/*
  File: In.java

  Iain Hewson

  January 2001
*/

package basicIO;

import java.io.*;
import java.util.*;

/**
 * This class was developed for use by 241 students in the first couple 
 * of labs. It provides quick access to Java's input classes without 
 * having to use the try-catch  mechanism. The drawback with this is that
 * methods like <code>getInt </code> simply exit without giving you any 
 * choice if an error is encountered which may not be what you want.
 * An error message will however be output to standard out.
 */
public class In {
    private static BufferedReader reader =
	new BufferedReader(new InputStreamReader(System.in));
    private static String lineSep = System.getProperty("line.separator");
    private static StringTokenizer tokenizedInput = new StringTokenizer("");
    private static String inputString = "";

    /** This class can not be instantiated */
    private In(){}


    /**
     * Read a line in from standard input.
     * @return the line which was read in.
     */
    public static String readLine() {
	inputString = null;
	tokenizedInput = new StringTokenizer("");

	try {
	    inputString = reader.readLine();
	} catch (IOException e) {
	    System.out.println("Error: " + e.getMessage());
	    System.exit(-1);
	}
	tokenizedInput = (inputString != null) ?
	    new StringTokenizer(inputString) :
	    new StringTokenizer("");

	return inputString;
    }


    /**
     * Read in lines from standard input until an EOF is received.
     * @return the lines which were read (not including the final newline).
     */
    public static String readLines() {
	String temp = "";
	inputString = null;
	tokenizedInput = new StringTokenizer("");

	try {
	    while ((temp = reader.readLine()) != null) {
		inputString = (inputString != null) ?
		    inputString + lineSep + temp :
		    temp;
	    }
	} catch (IOException e) {
	    System.out.println("Error: " + e.getMessage());
	    System.exit(-1);
	}
	tokenizedInput = (inputString != null) ?
	    new StringTokenizer(inputString) :
	    new StringTokenizer("");

	return inputString;
    }


    /**
     * Get the last line(s) of input read using class In
     * @return the last line(s) of input read.
     */
    public static String getLast() {
	return inputString;
    }


    /**
     * Tells if the most recently read input has any more tokens left
     * to retrieve.
     * @return if there are tokens left. 
     */
    public static boolean hasMoreTokens() {
	return tokenizedInput.hasMoreTokens();
    }


    /**
     * Tells how many tokens the most recently read input has left
     * to be retrieved.
     * @return the number of unretrieved tokens
     */
    public static int countTokens() {
	return tokenizedInput.countTokens();
    }


    /**
     * Retrieves the next token in the most recently read input
     * and moves forward to the following token. If there are no
     * more tokens to retrieve and error message is displayed and
     * the string "Error" is returned.
     * @return the next token.
     */
    public static String nextToken() {
	try {
	    return tokenizedInput.nextToken();
	} catch (NoSuchElementException e) {
	    System.out.println("Error: no more tokens to get.");
	    System.exit(-1);
	    return "This shouldn't be reached";
	}
    }


    /**
     * Retrieves the next token in the most recently read input
     * but doesn't move forward to the following token. If there are no
     * more tokens to retrieve an error message is displayed and the
     * program exits.
     * @return the next token.
     */
    public static String peekToken() {
	String result = "";
	String tempStr = "";

	if (tokenizedInput.hasMoreTokens()) {
	    result = tokenizedInput.nextToken();
	}
	tempStr = result;
	while (tokenizedInput.hasMoreTokens()) {
	    tempStr += " " + tokenizedInput.nextToken();
	}
	tokenizedInput = new StringTokenizer(tempStr);
	if (tokenizedInput.hasMoreTokens()) {
	    return result;
	} else {
	    System.out.println("Error: no more tokens to get.");
	    System.exit(-1);
	    return "This shouldn't be reached";
	}
    }


    /**
     * Read the next token from the most recently read input as an int.
     * If it can be parsed as an int then return the result.
     * If an error occurs an error message is printed and the program exits.
     * @return the next token as an int
     */
    public static int getInt() {
	int result = -1;
	try {
	    result = Integer.parseInt(nextToken());
	} catch (NumberFormatException e) {
	    System.out.println("Error: " + e.getMessage() +
			       " is not a valid integer");
	    System.exit(-1);
	}
	return result;
    }


    /**
     * Read the next token from the most recently read input as a long.
     * If it can be parsed as a long then return the result.
     * If an error occurs an error message is printed and the program exits.
     * @return the next token as a long
     */
    public static long getLong() {
	long result = -1;
	try {
	    result = Long.parseLong(nextToken());
	} catch (NumberFormatException e) {
	    System.out.println("Error: " + e.getMessage() +
			       " is not a valid long integer");
	    System.exit(-1);
	}
	return result;
    }


    /**
     * Read the next token from the most recently read input as a float.
     * If it can be parsed as a float then return the result.
     * If an error occurs an error message is printed and the program exits.
     * @return the next token as a float.
     * /
    public static float getFloat() {
	float result = -1;
	try {
	    result = Float.parseFloat(nextToken());
	} catch (NumberFormatException e) {
	    System.out.println("Error: " + e.getMessage() +
			       " is not a valid float");
	    System.exit(-1);
	}
	return result;
    }


    /**
     * Read the next token from the most recently read input as a double.
     * If it can be parsed as a double then return the result.
     * If an error occurs an error message is printed and the program exits.
     * @return the next token as a double.
     * /
    public static double getDouble() {
	double result = -1;
	try {
	    result = Double.parseDouble(nextToken());
	} catch (NumberFormatException e) {
	    System.out.println("Error: " + e.getMessage() +
			       " is not a valid double");
	    System.exit(-1);
	}
	return result;
	}*/
}

