/*
 * @(#)EventHandler.java	0.2 2001/04/03
 *
 * Copyright 2001 by Carnegie Mellon, All rights reserved.
 */

package kmt;
import java.util.*;

import edu.cmu.lti.kantoo.analyzer.*;
import edu.cmu.lti.kantoo.network.*;
import edu.cmu.lti.kantoo.shared.*;


/**
 * How to handle the KANTOO Servers given various GUI events
 *
 * @author  David Svoboda & Eric Nyberg
 * @version 0.2 2001/04/03
 */
public class EventHandler extends Worker {

  /**
   * Wrapper around KANTOOConnection; provides a tracer to catch log messages
   */
  public class KMTServer {
    /**
     * Server
     */
    private KantooConnection server;

    /**
     * thread to keep track of log messages
     */
    private TextConnectionWorker socketText;


    /**
     * @param name Name of server to connect to
     */
    public KMTServer(String name) {
      // establish connection, connect, and establish log
      if (name.equals("Analyzer"))
	server = new AnalyzerConnection();
      else server = new GeneratorConnection();
      server.connect();
      new Thread(new TextConnectionWorker( server.log(),
					   desktop.traceTextArea)).start();
    }
  }

  /**
   * The module that sends sentences to the Analyzer
   */
  private KMTServer analyzer;

  /**
   * @return the module that sends sentences to the Analyzer
   */
  public AnalyzerConnection getAnalyzer() {
    return (AnalyzerConnection) (analyzer.server);
  }

  /**
   * the module that sends IRs to the Generator
   */
  private KMTServer generator;

  /**
   * @return the module that sends IRs to the Generator
   */
  public KantooConnection getGenerator() {return generator.server;}


  /**
   * The desktop for status messages
   */
  KMTDesktop desktop;

  /**
   * @param desktop the desktop for status messages
   */
  public EventHandler(KMTDesktop desktop) {
    super();
    this.desktop = desktop;
    setServers();
  }

  public void setServers() {
    this.analyzer = new KMTServer("Analyzer");
    this.generator = new KMTServer("Generator");
  }

  /**
   * Class to indicate that some command should be sent to a KANTOO Server
   */
  private abstract class KMTCommand extends Command {
    /**
     * The actual info to send to the server
     */
    private String info;

    /**
     * @return the actual info to send to the server
     */
    public String getInfo() {return info;}

    /*
     * @param info the actual info to send to the server
     */
    public KMTCommand(String info) {this.info = info;}

    public void execute() {
      desktop.setStatus(toString());
      submit();
      desktop.setStatus("Ready.");
    }

    /**
     * Like execute, but doesn't have to worry about updating KMT desktop status
     */
    public abstract void submit();

    public String toString() {return super.toString() + ": " + info;}
  }


  /**
   * Indicates if the Generator should be called when analyzing a sentence.
   */
  boolean generatorActive = true;

  /**
   * Indicates that a sentence should be sent through the analyzer & generator
   */
  public class TranslateCommand extends KMTCommand {
    /*
     * @param sentence the actual sentence to send to the server
     */
    public TranslateCommand(String sentence) {super(sentence);}

    public void submit() {
      Issue issue = getAnalyzer().work( getInfo());
      desktop.setOutput( issue.toString());
      if (issue.translatable()) {
	List interlinguas = getAnalyzer().interlinguas();
	for (Iterator i = interlinguas.iterator(); i.hasNext();) {
	  String ir = (String) i.next();
	  desktop.appendOutput(ir  + "\n\n");
	  if (generatorActive)
	    desktop.appendOutput( getGenerator().query("WORK " + ir).substring("DATA ".length()));
	}
      }
    }
  }


  /**
   * A class for indicating that some kind of tracing should be toggled
   */
  public abstract class TraceCommand extends KMTCommand {
    /**
     * which server we are working with...
     */
    private KantooConnection server;

    /**
     * @return which server we are working with...
     */
    public KantooConnection getServer() {return server;}


    /**
     * @param server whether to use analyzer or generator
     * @param info   which info to change tracing in server
     */
    public TraceCommand(KantooConnection server, String info) {
      super(info);
      this.server = server;
    }
  }


  /**
   * How to turn module tracing on
   */
  static private final String MOD_TRACE_ON = "TRACE + + + ";

  /**
   * How to turn module tracing off
   */
  static private final String MOD_TRACE_OFF = "TRACE - - - ";


  /**
   * Class to handling module tracing
   */
  public class ModuleCommand extends TraceCommand {
    /**
     * whether tracing should be on or off
     */
    private boolean tracing;

    /**
     * @return whether tracing should be on or off
     */
    public boolean getTracing() {return tracing;}


    /**
     * @param server  which server to use
     * @param tracing whether tracing should be on or off
     * @param module  which module to change tracing
     */
    public ModuleCommand(KantooConnection server, boolean tracing, String module) {
      super(server, module);
      this.tracing = tracing;
    }

    public void submit() {
      String cmd = (getTracing() ? MOD_TRACE_ON : MOD_TRACE_OFF) + getInfo();
      String response = getServer().query( cmd);
      if (response.startsWith("RETURN ERROR"))
	desktop.fatalError(cmd + " => " + response.substring("RETURN ERROR".length()));
    }

    public String toString() {
      return getTracing() ? super.toString() :
	super.toString() + Log.SPACE + getTracing();
    }
  }


  /**
   * How to turn rule tracing on
   */
  static private final String RULE_TRACE_ON = "RULE_TRACE + + ";

  /**
   * How to turn rule tracing off
   */
  static private final String RULE_TRACE_OFF = "RULE_TRACE - - ";

  /**
   * Class fo handling rule tracing
   */
  public class RuleCommand extends TraceCommand {

    /**
     * @param server which server to use
     * @param info   which rule set to change
     */
    public RuleCommand(KantooConnection server, String info) {
      super(server, info);
    }

    public void submit() {
      String cmd = getInfo().startsWith("None") ?
	// Transform "turning on None" to "turning off All"
	RULE_TRACE_OFF + "All" + getInfo().substring(4) :
	RULE_TRACE_ON + getInfo();
      String response = getServer().query( cmd);
      if (response.startsWith("RETURN ERROR"))
	desktop.fatalError(cmd + " => " + response.substring("RETURN ERROR".length()));
    }
  }
}

