package JavaAgent.context;

import JavaAgent.agent.*;
import JavaAgent.resource.*;

import java.awt.*;
import java.util.Vector;

/**
 * AgentFrame provides a graphical interface for an Agent.<p>
 *
 * <hr>
 * Copyright (c) 1995, H. Robert Frost, Stanford University.
 * All rights reserved.<p>
 * Copyright (c) 1996, H. Robert Frost, Enterprise Integration Technologies,
 * Inc. All rights reserved.<p>
 *
 * RESTRICTED RIGHTS LEGEND: Use, duplication or disclosure by the 
 * Government is subject to restrictions as set forth in 
 * subparagraph(c)(1)(ii) of the Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 and in similar clauses in the
 * FAR and NASA FAR supplement.<p>
 * 
 * This software is bound by the terms and conditions listed in the
 * attached <a href="../LICENSE">LICENSE file</A>.
 * <hr>
 * @author <A HREF="http://cdr.stanford.edu/html/people/frost-bio.html"> Rob Frost</A>
 * @version 0.3 5/21/96 for Java(tm) Language Version 1.0.2
 */

public class AgentFrame extends Frame {

  protected String name;
  protected AgentContext context;

  protected int outgoing = 0;
  protected int incoming = 0;
  protected int sent = 0;
  protected int received = 0;

  /* GUI widgets */

  protected ViewResourcePanel vrp = null;
  protected LoadResourcePanel lrp = null;
  protected ViewMessagePanel vmp = null;
  protected LoadMessagePanel lmp = null;
  protected ComposeMessagePanel cmp = null;
  protected SystemMessagesPanel smp = null;
  
  protected MenuBar Controls = new MenuBar();
  protected Menu Action = new Menu("Action",true);
  protected MenuItem Quit = new MenuItem("Quit");

  protected Menu Messages = new Menu("Message", true);
  protected MenuItem ViewMessage = new MenuItem("View");
  protected MenuItem LoadMessage = new MenuItem("Load");
  protected MenuItem ComposeMessage = new MenuItem("Compose");
  
  protected Menu Resources = new Menu("Resource", true);
  protected MenuItem ViewResource = new MenuItem("View");
  protected MenuItem LoadResource = new MenuItem("Load");

  protected Menu Help = new Menu("Help", true);
  protected MenuItem HelpAbout = new MenuItem("About Java(tm) Agent");

  protected Panel SystemStatPanel = new Panel();
  protected Label NumReceived = new Label("0");
  protected Label NumSent = new Label("0");
  protected Label OutgoingLength = new Label("0");
  protected Label IncomingLength = new Label("0");
  protected Vector SystemMessageStorage = new Vector();


  /**
   * Constructor for an AgentFrame. Creates GUI components.
   * @param context AgentContext which created this gui.
   * @param title Title for the frame.
   */

  protected AgentFrame(AgentContext context, String title){
    super(title);
    this.name = title;
    this.context = context;

    setMenuBar(Controls);

    Controls.add(Action);
    Action.add(Quit);

    Controls.add(Messages);
    Messages.add(ComposeMessage);
    Messages.add(ViewMessage);
    Messages.add(LoadMessage);

    Controls.add(Resources);
    Resources.add(ViewResource);
    Resources.add(LoadResource);

    Controls.add(Help);
    Help.add(HelpAbout);
    Controls.setHelpMenu(Help);
 
    add("South",new Button("System Messages"));
    add("Center",SystemStatPanel);   
    SystemStatPanel.setLayout(new GridLayout(4,2));
    SystemStatPanel.add(new Label("Messages received:"));
    SystemStatPanel.add(NumReceived);
    NumReceived.setBackground(Color.white);
    SystemStatPanel.add(new Label("Messages sent:"));
    SystemStatPanel.add(NumSent);
    NumSent.setBackground(Color.white);
    SystemStatPanel.add(new Label("Outgoing buffer:"));
    SystemStatPanel.add(OutgoingLength);
    OutgoingLength.setBackground(Color.white);
    SystemStatPanel.add(new Label("Incoming buffer:"));
    SystemStatPanel.add(IncomingLength);
    IncomingLength.setBackground(Color.white);
  }

  /**
   * @return Agent contained by context.
   */

  protected Agent getAgent(){
    return context.getAgent();
  }
  
  /**
   * Called when an event happens in the AgentFrame. Used to take action
   * on menu bar selections.
   *
   * @param evt The event which triggered the method call.
   * @param arg Who called the method. For buttons, string name of button.
   */

  public boolean action(Event evt, Object arg) {
  
    if(evt.target instanceof MenuItem){
      MenuItem selected = (MenuItem)evt.target;
      if(selected.equals(Quit)){
	QuitAction();
      } else if(selected.equals(ComposeMessage)){
	if(cmp == null){
	  ComposeMessageAction();
	}
      } else if(selected.equals(ViewMessage)){
	if(vmp == null){
	  ViewMessageAction();
	}
      } else if(selected.equals(LoadMessage)){
	if(lmp == null){
	  LoadMessageAction();
	}
      } else if(selected.equals(ViewResource)){
	if(vrp == null){
	  ViewResourceAction();
	}
      } else if(selected.equals(LoadResource)){
	if(lrp == null){
	  LoadResourceAction();
	}
      } else if(selected.equals(HelpAbout)){
	HelpAboutAction();
      }
    } else if(arg.equals("System Messages")){
      SystemMessagesAction();
    } 
 
    return true;
  }

  /**
   * Generic method for creating a new top-level window with the specified
   * width, height and name to contain the specified panel.
   */
  
  protected void CreateNewFrame(Panel p, int width, int height, String name){
    Frame f = new Frame(name);
    f.add("Center", p);
    f.resize(width, height);
    f.show();
  }

  /**
   * Called when "Quit" is selected from the menu bar.
   */

  protected void QuitAction(){
    context.initiateTermination();
  }

  /**
   * Called by the AgentContext to dispose of the gui.
   */
  protected void terminate(){
    terminatePanels();
    dispose();
  }

  /**
   * Terminates all of the panels.
   */

  protected void terminatePanels(){
    terminatePanel(vrp);
    terminatePanel(lrp);
    terminatePanel(vmp);
    terminatePanel(lmp);
    terminatePanel(cmp);
    terminatePanel(smp);
  }

  /**
   * Terminates a specific panel.
   */

  protected void terminatePanel(InterfacePanel p){
    if(p != null){
      p.terminate();
    }
  }
  
  /**
   * Sets the InterfacePanel's reference to null.
   */

  protected void killPanel(InterfacePanel p){
    String class_name = p.getClass().getName();
    
    if(class_name.equals("JavaAgent.context.ViewResourcePanel")){
      vrp = null;
    } else if(class_name.equals("JavaAgent.context.LoadResourcePanel")){
      lrp = null;
    } else if(class_name.equals("JavaAgent.context.ViewMessagePanel")){
      vmp = null;
    } else if(class_name.equals("JavaAgent.context.LoadMessagePanel")){
      lmp = null;
    } else if(class_name.equals("JavaAgent.context.ComposeMessagePanel")){
      cmp = null;
    } else if(class_name.equals("JavaAgent.context.SystemMessagesPanel")){
      smp = null;
    }
  }
    
  /**
   * Create a SystemMessagesPanel.
   */
  
  protected void SystemMessagesAction(){
    smp = new SystemMessagesPanel(this);
    CreateNewFrame(smp,ContextParams.SMP_WIDTH,
		   ContextParams.SMP_HEIGHT,"System Messages");
  }
  
  /**
   * Called when "Compose Message" is selected from the menu bar.
   * Creates a new top-level frame for the interactive creations of
   * a KQML message. Has a default message to start with.
   */
  
  protected void ComposeMessageAction(){
    cmp = new ComposeMessagePanel(this, CreateDefaultMessage());
    CreateNewFrame(cmp,ContextParams.COMP_MESS_WD,ContextParams.COMP_MESS_HT,
		   "Compose Message");
  }
  
  /**
   * Returns a default message.
   */
  
  KQMLmessage CreateDefaultMessage(){
    KQMLmessage default_message = new KQMLmessage();
    default_message.addFieldValuePair("sender",getAgent().getName());
    default_message.addFieldValuePair("receiver","");
    default_message.addFieldValuePair("performative","");
    default_message.addFieldValuePair("language","");
    default_message.addFieldValuePair("ontology","");
    default_message.addFieldValuePair("content","");
    return default_message;
  }    

  /**
   * Called when "View Messages" is selected from the menu bar.
   * Creates a new top-level frame for the interactive viewing of
   * received KQML messages.
   */

  protected void ViewMessageAction(){
    if( ((Vector)(getAgent().getReceivedMessages())).size() > 0) {
      vmp = new ViewMessagePanel(this);
      CreateNewFrame(vmp,ContextParams.VIEW_MESS_WD,
		     ContextParams.VIEW_MESS_HT,"View Messages");
    } else {
      addSystemMessage("No Messages to View!");
    }
  }

  /**
   * Called when "Load Messages" is selected from the menu bar.
   * Creates a new top-level frame which allows the user to select a
   * file from which to load a set of messages.
   */
  
  protected void LoadMessageAction(){
    lmp = new LoadMessagePanel(this);
    CreateNewFrame(lmp, ContextParams.LOAD_MESS_WD,
		     ContextParams.LOAD_MESS_HT, "Load Messages");
  }

  /**
   * Called when some Agent resource has changed.
   * @param type String identifying the type of the resource.
   */

  public void resourceChanged(String type){
    if(type.equals("address")){
      informPanel(vrp, type);
    } else if(type.equals("interpreter")){
      informPanel(vrp, type);
    } else if(type.equals("language")){
      informPanel(vrp, type);
    } else if(type.equals("class")){
      informPanel(vrp, type);
    } else if(type.equals("file")){
      informPanel(vrp, type);
    } else if(type.equals("message")){
      informPanel(vmp, type);
    }
  }
  
  protected void informPanel(InterfacePanel p, String type){
    if(p != null){
      p.resourceChanged(type);
    }
  }

  /**
   * Called when "View Resources" is selected from the menu bar.
   * Creates a new top-level frame which allows the user to view the
   * resources currently possessed by the Agent.
   */
  
  protected void ViewResourceAction(){
    vrp = new ViewResourcePanel(this);
    CreateNewFrame(vrp, ContextParams.VIEW_RES_WD,
		     ContextParams.VIEW_RES_HT, "Resources");
  }

  /**
   * Called when "Load Resources" is selected from the menu bar.
   * Creates a new top-level frame which allows the user to load
   * new resources from somewhere on the Internet.
   */

  protected void LoadResourceAction(){
    lrp = new LoadResourcePanel(this);
    CreateNewFrame(lrp,ContextParams.LOAD_RES_WD,
		     ContextParams.LOAD_RES_HT, "Load Resource");
  }

  /**
   * Called when "About Java(tm) Agent" is selected from the menu bar.
   * Creates a new top-level frame which tells the user about the 
   * Functionality of the Java(tm) Agent.
   */

  protected void HelpAboutAction(){
    addSystemMessage("Help not yet implemented");
  }

  /**
   * Displays the message in the SystemMessages TextArea.
   * @param message The message to output.
   */
  
  public void addSystemMessage(String message){
    if(message.startsWith("System stat:")){
      String stat = message.substring(message.indexOf(":")+1);
      if(stat.equals("transmission started")){
	outgoing++;
	NumSent.setBackground(Color.green);
	OutgoingLength.setText("" +outgoing);
      } else if(stat.equals("transmission finished")){
	sent++;
	outgoing--;
	NumSent.setBackground(Color.white);
	OutgoingLength.setText("" +outgoing);
	NumSent.setText("" +sent);
      } else if(stat.equals("processing started")){
	incoming++;
	NumReceived.setBackground(Color.yellow);
	IncomingLength.setText("" +incoming);
      } else if(stat.equals("processing finished")){
	received++;
	incoming--;
	NumReceived.setBackground(Color.white);
	IncomingLength.setText("" +incoming);
	NumReceived.setText("" +received);
      } 
    } else {
      SystemMessageStorage.addElement(message);
      if(smp != null){
	smp.addSystemMessage(message);
      }
    }
  }  

  /**
   * Takes a panel created by the Agent and passed through the MessageOutput
   * object and displays it in a new top-level window.
   */
  
  public void addPanel(Panel p){
    CreateNewFrame(p,p.size().width, p.size().height,"Agent Generated GUI");
  }

}



















