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

package rec.fsm.speech;

import rec.agent.*;


import java.rmi.*;
import java.util.*;
import metaglue.*;
import rec.util.*;
import rec.sys.*;
import java.io.*;
import rec.fsm.*;

public class NameTrackerModule extends RemoteModuleImpl
    implements Registerable
{
  Hashtable nodes;

  // last id tinkered with--can be asked for it.
  Id last_Id;
  Id last_Node;
  Id last_Edge;
  Id last_Region;

  Surface surf;

  public NameTrackerModule( ModuleListener parent ) throws RemoteException
  {
    super( parent );
    
    nodes = new Hashtable();

    last_Id = null;

    System.err.println( "Constructed NameTracker connected to " + parent );
  }


  public boolean recognizeWidget( Surface s, Widget w )
  {
    // HACK TO GET HANDLE ON SURFACE--GRRRR....
    if ( surf == null )
      surf = s;

    last_Id = w.getId();
    if ( w instanceof rec.fsm.Edge )
      last_Edge = last_Id;
    if ( w instanceof rec.fsm.Node )
      last_Node = last_Id;
    if ( w instanceof rec.house.Region )
      last_Region = last_Id;

    if ( w instanceof rec.fsm.FSM )
      {
	if ( ! nodes.containsKey( w ) )
	  {
	    if ( ((rec.fsm.FSM)w).getName() != null )
	      {
		nodes.put( w, ((rec.fsm.FSM)w).getName() );
		tellPop( (rec.fsm.FSM)w, true );
	      }
	    s.register( this, w );
	  }
      }

    return false;
  }


  private void tellPop( rec.fsm.FSM w, boolean added )
  {
    String n = w.getName();
    
    int type = Types.UNKNOWN;
    if ( w instanceof rec.fsm.Edge )
      type = Types.EDGE;
    else if ( w instanceof rec.fsm.Node )
      type = Types.NODE;
    //    else if ( w instanceof rec.house.Region )
    //      type = Types.REGION;

    tellPop( n, type, added );
  }

  private void tellPop( String name, int type, boolean added )
  {
    try 
      {
	NameTracker n = new NameTracker( name, type, added );

	System.err.println( "Telling pop new name " + n );
	parent.ring( n );
      }
    catch ( RemoteException e )
      {
	e.printStackTrace();
      }
  }

  public void removed( Widget w )
  {
    //Console.writeln( "Seeing thing disappear." );
    nodes.remove( w );
    if ( ((rec.fsm.FSM)w).getName() != null )
      tellPop( (rec.fsm.FSM)w, false );
  }

  public void replaced( Widget ow, Widget nw )
  {
    //    last_Id = nw.getId();

    nodes.remove( ow );
    if ( ((rec.fsm.FSM)ow).getName() != null )
      tellPop( (rec.fsm.FSM)ow, false );

    if ( nw instanceof rec.fsm.FSM )
      {
	rec.fsm.FSM n = (rec.fsm.FSM)nw;
	if ( n.getName() != null )
	  {
	    nodes.put( nw, n.getName() );
	    tellPop( (rec.fsm.FSM)nw, true );
	  }
      }
    else
      surf.unregister( this, nw );
  }

  public void replaced( Widget ow, Collection nws )
  {
    Iterator it = nws.iterator();
    while( it.hasNext() )
      replaced( ow, (Widget)it.next() );
  }

  public void altered( Widget w, Transition t )
  {
    //    last_Id = w.getId();

    rec.fsm.FSM n = (rec.fsm.FSM)w;
    String name = (String)nodes.get( n );
    if ( ( name == null ) || !name.equals( n.getName() ) )
      {
	if ( name != null )
	  {
	    nodes.remove( w );
	    tellPop( n, false );
	  }
	if ( n.getName() != null )
	  {
	    nodes.put( n, n.getName() );
	    tellPop( n, true );
	  }
      }
  }


  /**
   * Return the Id of the last object hit by anything.
   */
  public Object query( Object q ) throws RemoteException
  {
    int v = ( (Integer)q ).intValue();

    switch ( v )     {
    case Types.EVERYTHING:
      return last_Id;
    case Types.NODE:
      return last_Node;
    case Types.EDGE:
      return last_Edge;
      //    case Types.REGION:
      //      return last_Region;
    }
    
    //Console.writeln( "ERROR: Invalid type in NameTrackerModule." );
    return null;
  }


}


