package FDATI;

import SModeling.*;
import RemoteService.agent.*;
import RemoteService.resource.*;
import JavaAgent.resource.*;
import java.util.*;
import java.awt.*;
import java.net.*;
import java.io.*;

/**
 * Subclass of Service which provides an interface for the Fixture Design and
 * Analysis Tool at CMU.<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 FDATService extends RemoteService.resource.Service{
  
  /**
   * Is this the first execution of this Service?
   */
  private boolean first_execution = true;

  /**
   * Name of ServiceAgent which supplied the Service.
   */
  public static String service_agent = "FDAT";

  /**
   * keys are model names, objects are models 
   */
  protected Hashtable Models = new Hashtable(); 
  
  /**
   * keys are model names, objects are model files.
   */
  protected Hashtable model_files = new Hashtable(); 

  /**
   * Graphical interface.
   */
  private FDATI fdati = null;
  
  private ResultPanel results = null;

  /**
   * Executes the FDAT Service interface.
   * If this is the first execution of the service, the FDAT Interpreter will be
   * loaded and a set of example models will be retrieved.
   */
  
  public void run(){
    if(first_execution){
      first_execution = false;
      /* load the FDAT onotology */
      load_Interpreter();
      /* get the sample model files */
      retrieve_models();
    } else {
      /* open the GUI */
      open_gui();
    }
  }
  
  /**
   * Stops the service.
   */

  public void stop(){
    if(fdati != null){
      fdati.stop();
    }
    if(results != null){
      Frame f = (Frame)results.getParent();
      f.dispose();
      results = null;
    }
  }

  /**
   * Loads the FDATInterpreter.
   */

  private void load_Interpreter(){
    parent.getResource("interpreter").addElement("FDAT",
					      new FDATInterpreter(), true);
  }

  /**
   * Send a message to the FDAT agent requesting the location of the sample
   * models.
   */

  private void retrieve_models(){
    KQMLmessage msg = new KQMLmessage("(evaluate :receiver " + service_agent +
				      " :sender " + parent.getName() +
				      " :language KQML :ontology FDAT" +
				      " :content (ask-models))");
    parent.sendMessage(msg);
  }

  /**
   * tell-models message received from the FDAT agent.
   * @param models Keys are model names, objects are files which contain
   * the model description.
   */

  public void received_models(Hashtable models){    
    this.model_files = models;
    load_models();
    open_gui();
  }

  /**
   * Creates model objects from the model files.
   */

  private void load_models(){
    Enumeration e = model_files.keys();
    while(e.hasMoreElements()){
      try{
	String name = (String)e.nextElement();
	FileInputStream fis = new FileInputStream((File)model_files.get(name));
	Models.put(name,ObjectFormatParser.ParseInputStream(fis));
      } catch (IOException ex){
	addSystemMessage("Error creating model object from file.",ex);
      }
    }
  }

  /**
   * Create the FDAT interface.
   */
  
  private void open_gui(){
    if(parent.hasGUI()){
      if(fdati == null){
	fdati = 
	  new FDATI(this,parent);
	fdati.resize(300,400);
	parent.addPanel(fdati);
      }
    }
  }

  /**
   * Called to submit the current fixturing plan to the FDATAgent for
   * analysis.
   * @param name Name of the fixturing plan.
   * @param dir Directionality for analysis.
   * @param dim Dimensionality for analysis.
   * @param dir_vec Direction vector for "directional" analysis.
   * @param model The model whose fixture points are being analyzed.
   */

  void submit_fixels(String name, String dir, String dim, hpoint dir_vec,
		     model M){
    KQMLmessage msg = 
      new KQMLmessage("(evaluate :receiver " + service_agent +
		      " :sender " + parent.getName() +
		      " :language KQML :ontology FDAT)");
    String fixel_str = "(" +dim + " " + dir + " ";
    if(dir.equals("directional")){
      fixel_str = fixel_str + Float.toString(dir_vec.getx()) + " " +
	Float.toString(dir_vec.gety()) + " " +
	  Float.toString(dir_vec.getz()) + " ";
    }
  
    int num_fix_points = M.fix_points.size();
    
    for(int i = 0; i < num_fix_points; i++){

      fix_point temp = (fix_point)M.fix_points.elementAt(i);
      
      fixel_str = fixel_str + Float.toString(temp.x()) + " " +
	Float.toString(temp.y()) + " " +
	  Float.toString(temp.z()) + " " +
	    Float.toString( M.get_dircos(temp,1)) + " " +
	      Float.toString( M.get_dircos(temp,2)) + " " +
		Float.toString( M.get_dircos(temp,3)) + " ";
    }

    fixel_str = fixel_str + ")";
    msg.addFieldValuePair("content","(submit-fixels :name " + name +
			  " :fixels " + fixel_str + ")");
    parent.sendMessage(msg);
  }

  /**
   * submission-results message received from the FDATAgent.
   * @param name Fixturing plan name.
   * @param results Submission results.
   */

  public void submissionResults(String name, boolean stable, 
				int minimum, Vector redundant){
    if(parent.hasGUI()){
      results = 
	new ResultPanel(name, stable, minimum, redundant);
      results.resize(250,200);
      parent.addPanel(results);
    } else {
      parent.addSystemMessage("Submission results for " + name +
			      ": " + (stable?"stable":"unstable") +
				      ", theoretical minimum: " + 
				      minimum);
    }
  }

  protected void killFDATI(){
    fdati = null;
  }

  protected void killResults(){
    results = null;
  }

}






