package JavaAgent.oplan;

import JavaAgent.agent.*;
import JavaAgent.resource.*;
import JavaAgent.context.ContextInterface;

import java.io.*;
import java.lang.Runtime;
import java.net.URL;

/** 
** An OPAgent is basically a normal JAT Agent that also runs an OPlan 
** Process. An OPAgent is created from the class OPAgentContext.
** @see OPAgentContext
*/

public class OPAgent extends Agent {

  /** 
  ** The constructor for an OPAgent directly calls standard agent
  ** constructor without changing the parameters. The OPlan Process that
  ** this OPAgent will run is started in the <tt>init()</tt> method.
  ** @param context the ContextInterface for this OPAgent
  ** @param n the name of this agent
  ** @param init_url the URL pointing to the initialization messages
  ** @param shared a URL pointing to some shared location
  ** @param shared_dir a shared directory
  ** @param working_dir the working directory for this OPAgent
  */
  public OPAgent(ContextInterface context, String n, URL init_url, URL shared, 
	       File shared_dir, File working_dir) {
    super(context, n, init_url, shared, shared_dir, working_dir);
  }

  /**
  ** This function first creates the ResourceManager and MessageHandler as
  ** for any Agent. Then it adds the broker's address as a resource. This is 
  ** usually done with the first message from the init-file, but OPAgents get
  ** the address from their OPAgentContext which expects it as a command line
  ** parameter. Next an OPAgent attempts to start an OPlan Process for which 
  ** it expects to find OPlan in the directory 
  ** <tt>/hame/gw/oplan-kcl/bin/</tt>. If this succeeds it also starts an 
  ** OPReader and an OPWriter which are threads for the communication with 
  ** OPlan. Other Agents also read the init-file when this function is called,
  ** but OPAgents do this in the function <tt>sendInitMessages()</tt> below,
  ** i.e. not here.
  */
  public void init() {
    if(working_dir != null) {
      io_enabled = true;
    }
    resources = new ResourceManager(this);
    handler = new MessageHandler(this);

    // add the broker's address as resource:
    getResource("address").addElement("ANS", 
        ((OPAgentContext)context).getBrokerAddress(), true);

    // trying to start O-Plan:
    try {
      oPlanProcess = Runtime.getRuntime().exec(
          "/hame/gw/oplan-kcl/bin/oplan -connect -no -windows");
      fromOPlan = new OPReader(this, oPlanProcess);
      fromOPlan.start();
      // give OPlan some time before writing messages to it
      try {
	Thread.currentThread().sleep(1000);
      } catch (InterruptedException ie) {
	// don't worry if this fails
      }
      toOPlan = new OPWriter(this, oPlanProcess);
      toOPlan.start();
    } catch (IOException e) {
      addSystemMessage("Error: Failed to start O-Plan!");
    }
  }

  /**
  ** This function sends the messages which are automatically sent out at 
  ** startup. Currently this is only the message to the ANS telling it the
  ** address of this agent. This function also loads the initialization 
  ** messages to this agent from the init file which may cause further
  ** messages to be sent to the broker. Note that this is different from 
  ** normal JAT Agents.
  */
  public void sendInitMessages() {
    ((OPAgentContext)context).SubmitAddress();
    loadInitFile(init_url);
  }

  /**
  ** Called when the executable class which contains the OPAgent terminates.
  ** The agent sends a remove-address message to the ANS and terminates the
  ** OPlan Process.
  */
  public void initiateTermination() {
    handler.initiateTermination();
    toOPlan.stop();
    fromOPlan.stop();
    oPlanProcess.destroy();
  }

  /** 
  ** the handle of the OPlan Process strted by this OPAgent
  */
  public Process oPlanProcess;

  /** 
  ** the OPReader for reading from the OPlan Process
  */
  public OPReader fromOPlan;

  /** 
  ** the OPWriter for writing to the OPlan Process
  */
  public OPWriter toOPlan;

}
