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

package rec.house.speech;


import java.rmi.*;
import java.util.*;
import metaglue.*;
import rec.util.*;
import rec.sys.*;
import java.io.*;
import rec.house.*;
import rec.agent.*;

public class RegionWatcherModule extends RemoteModuleImpl
    implements Registerable
{
  Surface surface;

  public RegionWatcherModule( ModuleListener parent ) throws RemoteException
  {
    super( parent );
    
    System.err.println( "Constructed RegionWatcher connected to " + parent );
  }


  public boolean recognizeWidget( Surface s, Widget w )
  {
    // HACK TO GET HANDLE ON SURFACE--GRRRR....
    if ( surface == null )
      surface = s;
    
    if ( w instanceof Region )
      {
	Region r = (Region)w;
	surface.register( this, r );
	checkRegion( r );
      }

    return false;
  }


  public void checkRegion( Region r )
  {
    String n = r.getName();
    if ( n != null )
      {
	HashSet st = findSameSizeAs( r, 0.8 );

	if ( n.equals( "bathroom" ) )
	  {
	    if ( borders( r, "kitchen" ) )
	      tellPop( "your bathroom is bordering a kitchen." );
	    else if ( containsType( st, "kitchen" ) 
		      || containsType( st, "bedroom" ) )
	    {
	      tellPop( "your bathroom is the same size as your kitchen" );
	    }
	  }
	else if ( n.equals( "kitchen" ) )
	  {
	    if ( borders( r, "bathroom" ) )
	      tellPop( "your bathroom is bordering a kitchen." );
	    else if ( containsType( st, "bathroom" ) )
	    {
	      tellPop( "your kitchen is the same size as your bathroom" );
	    }
	  }
	else if ( n.equals( "bedroom" ) )
	  {
	    if ( borders( r, "bathroom" ) )
	      tellPop( "your bathroom is bordering a kitchen." );
	    else if ( containsType( st, "bathroom" ) )
	    {
	      tellPop( "your bedroom is the same size as your bathroom" );
	    }
	  }
      }
  }
  

  boolean containsType( HashSet st, String name )
  {
    Iterator it = st.iterator();
    while( it.hasNext() )
      {
	Region r = (Region)it.next();
	if ( name.equals( r.getName() ) )
	  return true;
      }

    return false;
  }

  /**
   * @return set of all regions which are (if s = r's size)
   *          [s/order, s*order]
   */
  HashSet findSameSizeAs( Region reg, double order )
  {
    double size = reg.area();
    double low = size/order;
    double high = size*order;

    Iterator it = surface.getWidgetsIterator();

    HashSet st = new HashSet();

    while ( it.hasNext() )
      {
	Widget w = (Widget)it.next();
	if ( ! ( w instanceof Region ) )
	  continue;

	Region r = (Region)w;
	double s2 = r.area();

	if ( (low <= s2) && (s2 <= high) )
	  st.add( r );
      }

    return st;
  }


  public boolean borders( Region r, String thing )
  {
    Iterator e = r.walls();
    while( e.hasNext() )
      {
	Wall w = (Wall)e.next();
	
	if ( !w.isBorder() )
	  continue;

	Iterator e2 = w.regions();
	while ( e2.hasNext() )
	  {
	    Region r2 = (Region)e2.next();
	    if ( r2.equals( thing ) )
	      return true;
	  }
      }
    return false;
  }

  private void tellPop( String message )
  {
    try 
      {
	WatcherMessage msg = new WatcherMessage( new Id(), message );

	System.err.println( "Telling pop: " + msg );
	parent.ring( msg );
      }
    catch ( RemoteException e )
      {
	e.printStackTrace();
      }
  }

  public void removed( Widget w )
  {
    Console.writeln( "Seeing thing disappear." );
  }

  public void replaced( Widget ow, Widget nw )
  {
    if ( ! ( nw instanceof Region ) )
      surface.unregister( this, nw );
  }

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

  public void altered( Widget w, Transition t )
  {
    checkRegion( (Region)w );
  }


  public Object query( Object q ) throws RemoteException
  {
    return null;
  }


}


