// (c) MIT 2003.  All rights reserved.

package rec.fsm.speech;

import rec.agent.*;


import java.rmi.*;
import java.util.*;
import speech.*;
import speech.tools.*;
import metaglue.*;
import rec.core.*;
import rec.sys.*;
import rec.fsm.*;
import rec.util.*;

public class NamerAgent extends SpeechAgent
    implements Namer, ModuleListener
{
  Sketch sketch;
  AppGrammar grammar;
  Asker asker;

  Hashtable names;
  ModuleListener namerListener;
  RemoteModule namerModule;

  public NamerAgent( ) throws RemoteException
  {
    grammar = loadGrammar();
    makeAlwaysActive( grammar );
    
    // get the sketch agent
    sketch = (Sketch)reliesOn( "rec.agent.Sketch" );

    asker = (Asker)reliesOn( "speech.tools.Asker" );

    names = new Hashtable();
    namerListener = this;

    ModuleMaker mm = new ModuleMaker( "rec.fsm.speech.NameTrackerModule" );
    namerModule = sketch.installModule( mm, namerListener );
  }


  /**
   * Incoming speech goes through here.
   */
  public void acceptedTagsResult (Hashtable tags) throws RemoteException
  {
    int type = Types.EVERYTHING;

    System.err.println( "Namer activated." );
    if ( tags.containsKey( "namephrase" ) )
      {
	String pc = "it";
	if ( tags.containsKey( "node" ) )
	  {
	    type = Types.NODE;
	    pc = "the node";
	  }
	else if ( tags.containsKey( "edge" ) )
	  {
	    pc = "the edge";
	    type = Types.EDGE;
	  }
	
	String name = null;
	if ( tags.containsKey( "name" ) )
	  name =  (String) tags.get( "name" );
	else
	  name = asker.askFree( "What do you want to name " + pc + "?" );
	
	System.err.println( "Got the answer of " + name );
	 name = fixName( name );
	 namer( type, name );
      }
  }


  String fixName( String n )
  {
    StringTokenizer st = new StringTokenizer( n );
    String t = "";
    while( st.hasMoreTokens() )
      {
	String nxt = st.nextToken();
	if ( nxt.equals( "or" ) )
	  t += " |";
	else if ( nxt.equals( "one" ) )
	  t += " 1";
	else if ( nxt.equals( "zero" ) )
	  t += " 0";
	else t += " " + nxt;
      }

    return t.trim();
  }

  /**
   * @param what   null means everything, else it switches in its
   *               known classes, and it and all children are nuked.
   */
  public void namer( int type, String what_name ) throws RemoteException
  {
    final String name = what_name;

    // get the object
    Integer tp = new Integer( type );
    final Id id = (Id)namerModule.query( tp );
   
    // make the gremlin which will name it
    Gremlin g = new Gremlin( ) {

      public int tweak( Surface surf )
	{
	  Iterator e = surf.getWidgetsIterator();
	  boolean done = false;
	  while( !done && e.hasNext() )
	    {
	      Widget w = (Widget)e.next();
	      if ( (w instanceof FSM) && (id.equals( w.getId() )) )
		{
		  surf.beginEvent();
		  System.err.println( "Setting " + w + "'s name to " + name );
		  ( (FSM)w ).setName( name );
		  done = true;
		}
	    }
	  
	  return done ? 1 : 0;
	}
    };

    // name the object
    sketch.takeGremlin( g );
  }


  public Object ring( Object o ) throws RemoteException
  {
    NameTracker n = (NameTracker)o;
    
    if ( n.added )
      {
	names.put( n.name, n.name );
      }
    else
      {
	names.remove( n.name );
      }
    System.err.println( "I know we have " + names.keys() + " names now!" );
    
    return null;
  }
  
  
}



