package kraft.monitor;

import java.io.*;
import java.util.Vector;
import java.util.Enumeration;
import kraft.TermInString;
import Linja.*;


/** A Linja client that reads in a File made up of Prolog 
  * term structures.
  * These structures will be "outed" to the Linda server
  * one by one, and after a pause, are then "in"ed again.
  *
  * This class is used by KraftMonitor to load a 'batch file'
  * of messages to be visualised by the Monitor. Linda makes 
  * duplicates of the messages so the client 'tidies up'
  * after itself.
  *
  * NB: start() must be called to start the client working
  *
  *@author Ted Francis
  *@see KraftMonitor
  */

//===========================================
public class FileBasedClient extends Thread {
//===========================================

  File        file;
  LindaClient linda;
  Vector      messages;


  /** Initialise the client to read from the given file.
    * Connects to the linda server at l_host:l_port
    */
  FileBasedClient(File f, String l_host, int l_port) {
    file     = f;
    messages = new Vector();
    linda    = new LindaClient(l_host,l_port);
  }


  /** The main execution of the thread.
    * Reads lines from file until one is terminated by full stop,
    * then outs the term to linda.
    *
    * Cleans up the messages afterwards.
    */
  public void run() {

    if( ! (file.exists() && file.isFile() && file.canRead())) {
      System.err.println("\nCannot read from file: "+file.getPath());
      stop();
    }
    else{ 
      LineNumberReader reader=null;
      try{ 
	String line;
	reader = new LineNumberReader(new FileReader(file));

	System.out.println("\nFilebasedClient starting file parse:");

	while((line = reader.readLine()) != null) {

	  if(line.equals("") || line.startsWith("#") || line.startsWith("%")) {
	    //skip blank lines and comments
	    ;
	  }
	  else {
	    //read lines until we encounter one ended with a '.'
	    //--------------------------------------------------
	    StringBuffer buf = new StringBuffer(line.trim());
	
	    while(line.trim().endsWith(".")==false) {
	      line=reader.readLine();
	      if(line==null) 
		throw new IOException("End of file reached when parsing term");
	      buf.append(line.trim());
	    }
	    String tmp  = buf.toString();
	    tmp = tmp.substring(0,tmp.length()-1); //strip off final '.'


	    // This is commented out as TermInString cannot deal with
	    // very complex term structures (eg with infix operators etc..)
	    //
	    // If the TermInString class is updated to do this, it would 
	    // provide a more secure way of  validating the files written
	    // by users
	    //
	    //------------------------------------------
	    //TermInString term = new TermInString(tmp);
	    //got past here, so its a valid term
	    //------------------------------------------

	    System.out.println("read from line " +reader.getLineNumber()+": "+tmp);
	    messages.addElement(tmp); //add to the list of messages
	  }//else

	}//while
	reader.close();
	System.out.println("finished reading file");

      }//try
      catch(Exception e) {
	System.err.print("\nProblem reading from file: "+file.getPath());
	if(reader!=null)
	  System.err.println("on or before line "+reader.getLineNumber());
	else System.err.println();
	System.err.println("--->error = " +e);	
	e.printStackTrace();
	stop();
      }	

      System.out.println("\nNow \"out\"ing messages to linda");
      try{
	linda.connect();
	Enumeration e = messages.elements();
	while(e.hasMoreElements()) {
	  linda.out((String)e.nextElement());
	}
	linda.disconnect();
	
      }//try
      catch(IOException e) {
	System.err.println("\nProblem \"outing\" to linda: "+e);
      }
      
      //give linda time to make the duplicates
      try{ Thread.sleep(10000); }
      catch(InterruptedException e) {}

      System.out.println("\nNow removing messages from linda");
      try{
	linda.connect();
	linda.set_timeout(500);
	Enumeration e = messages.elements();
	while(e.hasMoreElements()) {
	  linda.in_noblock((String)e.nextElement());
	}
	linda.disconnect();
      }
      catch(IOException e) {
	System.err.println("\nProblem \"in'ing\" from linda: "+e);
      }
    }//end else
    System.out.println("FileBasedClient: finished");
    stop();
  }//end run


}//end FileBasedClient
