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

package rec.house;


import java.util.*;
import java.awt.*;
import rec.util.*;
import rec.sys.*;
import rec.geo.*;
import rec.core.*;

/**
 * This cuts regions apart if a line gets drawn across them
 */
public class RegionCutter extends Recognizer
{
  public static final double BREAK = 20;

  public RegionCutter()
  {
  }

  ////////////////////////////////////////////////////////////////////////////

  /**
   * Recognizes on new lines, before they get a shot at region building
   * by normal means.
   * If the line is a Wall and the wall borders any region already
   * then do not look for a cut.
   */
  public boolean recognize( Surface s, Widget w )
  {
    // true if the w gets replaced by Wall or some such.

    boolean changed = false;
    WLine l = (WLine)w;
    GPoint p1 = l.getHead();
    GPoint p2 = l.getTail();

    // if the line is a Wall and the wall borders any region already
    // then do not look for a cut.
    if ( ( l instanceof Wall ) && ( ((Wall)l).isBorder() ) )
      return false;

    // go through all regions looking for one which is cut by the
    // wall.
    Iterator e = s.getWidgetsIterator();
    while( e.hasNext() )
      {
	Object o = e.next();
	if (! ( o instanceof Region ) )
	  continue;
	Region r = (Region)o;

	// check to see if the line's endpoints lie on region's border.
	// (could check for intersection if we wished.)
	if ( r.includes( p1, BREAK ) && r.includes( p2, BREAK ) )
	  {
	    // get the 2 regions formed by split
	    HashSet set = r.splitOn( l );
	    
	    // if the set is bad (i.e. wall along edge of region)
	    // then can it.
	    if ( set == null )
	      {
		Console.writeln( "Wall bordering region--no cut made" );
		continue;
	      }

	    // cut the region into 2 pieces
	    s.replaceWidget( r, set, true );

	    // attach the cutting edge
	    Wall wall = null;
	    if ( l instanceof Wall )
	      wall = (Wall)l;
	    else
	      {
		changed = true;
		wall = Wall.changeToWall( s, l );	      
	      }

	    Iterator e2 = set.iterator();
	    while( e2.hasNext() )
	      {
		Region reg = (Region)e2.next();

		// move region so it is painted first
		// so doors look okay--HACK HACK!
		s.shuffleToBottom( reg );

		wall.addRegion( reg );
		reg.addWall( wall );
	      }

	    if ( changed )
	      return true;
	  }
      }
    return changed;
  }


  public Iterator getInputTypes()
  {
    Vector v = new Vector();

    v.addElement( "rec.core.WLine" );
    v.addElement( "rec.house.Wall" );

    return( v.iterator() );
  }

  public Iterator getOutputTypes()
  {
    Vector v = new Vector();

    v.addElement( "rec.house.Region" );

    return( v.iterator() );
  }
}

////////////////////////////////////////////////////////////////////////////////
