import rebelsky.io.SimpleInput;
import rebelsky.io.SimpleOutput;

/**
 * A simple interactive tester for token sequences.  You pass a
 * token sequence to this class and it gives you a simple textual
 * interface for browsing that sequence.
 *
 * @author Samuel A. Rebelsky
 * @version 1.0 of October 2002
 */
public class TokenStreamTester {
  // +--------+-------------------------------------------------------------
  // | Fields |
  // +--------+

  /**
   * The object used to read input (presumably from the keyboard.
   */
  protected SimpleInput in;

  /**
   * The object used to write output (presumably to the screen).
   */
  protected SimpleOutput out;

  /**
   * The token stream we're testing.
   */
  protected TokenStream tokens;

  /**
   * The underlying character stream.
   */
  protected AdvCharStream acs;


  // +--------------+-------------------------------------------------------
  // | Constructors |
  // +--------------+

  /**
   * Build a new tester to test the specified character stream.
   */
  public TokenStreamTester(TokenStream tokens, AdvCharStream acs) {
    this.tokens = tokens;
    this.acs = acs;
    this.in = new SimpleInput();
    this.out = new SimpleOutput();
  } // TokenStreamTester(AdvCharStream)

  // +---------+------------------------------------------------------------
  // | Methods |
  // +---------+

  /**
   * Run the tester.
   */
  public void interact() {
    boolean done = false;	// Are we done getting input?
    String response;		// A response typed by the user
    char resp;			// The first character of that response

    // Keep going until the user indicates we're done
    while (!done) {
      // Print a prompt
      out.print("[line: " + acs.line()  + ", pos: " + acs.pos() + "]");
      out.print("> ");
      // Get the response
      response = in.readLine();
      if (response.length() != 0) {
        try {
          // Decide what to do based on that response
          switch (response.charAt(0)) {
            case 'h':				// Help
            case '?':
              out.println("h: print this help message");
              out.println("P: peek at the next token");
              out.println("N: read the next token");
              out.println("C: check for end of input");
              break;
            case 'p':
              try { out.println("Next character: " + acs.peek()); }
              catch (EndOfStream eos) { out.println("No characters remain."); }
              break;
            case 'P':
              try { out.println("Next token: " + tokens.peek().toString()); }
              catch (EndOfStream eos) { out.println("No tokens remain."); } 
              break;
            case 'N':
              try { out.println("Next token: " + tokens.next().toString()); }
              catch (EndOfStream eos) { out.println("No tokens remain."); } 
              break;
            case 'q':
            case 'Q':
              done = true;
              break;
          } // switch (response.charAt(0)
        } // try
        catch (Exception e) { out.println("BOOM: " + e); }
      } // if (response.length() != 0)
    } // while
  } // interact()

  /**
   * Dump a token stream to standard output.  Used mostly for testing
   * purposes.
   */
  public static void dump(TokenStream tokens) {
    try {
      while (tokens.hasMore()) {
        System.out.println(tokens.next());
      } // while
    } // try
    catch (EndOfStream eos) {
      System.out.println("Reached the end of the stream.");
    }
    catch (Exception e) {
      System.out.println(e);
    }
  } // dump(TokenStream)
} // class TokenStreamTester

