/* Copyright (c) 2008 Charles Rich and Worcester Polytechnic Institute.
 * All Rights Reserved.  Use is subject to license terms.  See the file
 * "license.terms" for information on usage and redistribution of this
 * file and for a DISCLAIMER OF ALL WARRANTIES.
 * 
 * Refactored from Guide by willie
 */
package edu.wpi.cetask.guide;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.PrintStream;

public class TextUI implements ITaskUI {

	//private final PrintStream out = System.out, err = System.err; // to restore                             

	   private BufferedReader input; // current input
	   private File file;   // current input source file (or null)

	   private InputThread inputThread;
	   
	   private boolean running = true;
	   
	public TextUI(String filename) {
	      if ( filename == null ) input = systemIn();
	      else source(filename);
	      
	   inputThread = new InputThread();   
	   new Thread(inputThread).start();
	}

	public void deallocate() {
		running = false;
		synchronized (inputThread) {
			inputThread.notify();			
		}
	}

	public void println(Object object) {
		String line = "    " + object;
		System.out.println(line);
		Guide.guide.log(line);
	}
	
	public void prompt () {
		System.out.print(Guide.PROMPT);
		synchronized (inputThread) {
			inputThread.notify();
		}
	}
	
	   private static BufferedReader systemIn () { 
		      return new BufferedReader(new InputStreamReader(System.in));
		   }

	   /**
	    * Start reading user input from given file.
	    */
	   public void source (String filename) {
	      if ( file != null ) 
	         Guide.warning("Ignoring recursive source "+filename);
	      else try {
	         file = new File(filename);
	         input = new BufferedReader(new FileReader(file));
	      } catch (FileNotFoundException e) {
	         Guide.exception(e);
	         file = null;
	      }
	   }

	   private class InputThread implements Runnable {
		   public void run() {
				try {
					synchronized (this) {
						wait();
					}
				}
				catch (Throwable e) { 
					Guide.exception(e); 
				} 
			   while (running) {
				try {
					String line = input.readLine();
					
			        if ( line == null && file != null ) {
			            // switch input back to user
			            file = null;
			            input = systemIn(); 
			            line = input.readLine();
			         }
			         if ( line == null ) return;
			         if ( line.startsWith(Guide.PROMPT) ) 
			            // for convenience to make source files using keep-lines in Emacs
			            line = line.substring(Guide.PROMPT.length());
			         if (file != null) {
			        	 println(line);
			         } else {
				         Guide.guide.log(line);
			         }
			         //(file == null || System.out == logStream ? logStream : System.out)
			         //   .println(line);
			         if ( line.startsWith("#") ) return;  // skip comment line
			
					Guide.guide.addInput(line);
					synchronized (this) {
						wait();
					}
				}
				catch (Throwable e) { 
					Guide.exception(e); 
				} 
			   }
		   }
	   }
}
