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

package rec.house;


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

public class WallBreaker extends Recognizer
{
  public final double BREAK = 20.0;

  int cur_name = 0;

  public WallBreaker()
  {
  }
  
  public boolean recognize( Surface s, Widget w )
  {
    WLine line = (WLine)w;
    GSegment g1 = line.getLine();

    // look for a wall or line to break
    Iterator e = s.getWidgetsIterator();
    while( e.hasNext() )
      {
	Object o = e.next();
	if ( o instanceof WLine )
	  {
	    WLine line2 = (WLine)o;
	    GSegment g2 = line2.getLine();

	    //	    Console.writeln( "g1=" + g1 + ", g2=" + g2 );
	    GPoint x = g1.getIntersection( g2 );
	    //	    Console.writeln( "intersect = " + x );

	    // if lines parallel
	    if ( x == null )
	      continue;

	    // if intersection point in bounds of both lines then we
	    // have a cross (an X or T intersection)
	    if ( g1.includes( x, BREAK ) && g2.includes( x, BREAK ) )
	      {
		// if the break is not near endpoints we divide into 2 pieces
		// (X or T intersections)
		if ( ! line.getHead().includes( x, BREAK )
		     && ! line.getTail().includes( x, BREAK ) )
		  {
		    // break the line
		    split( s, line, x );

		    return true;
		  }

		// break any line we hit (T intersections)
		if ( !line2.getHead().includes(x,BREAK) 
		     && !line2.getTail().includes(x,BREAK) )
		  {
		    // split the edge.
		    split( s, line2, x );
		  }
	      }
	  }
      }

    return false;
  }
  

  /**
   * Replace a single line with 2 lines with a cut at 'cut'
   */
  public void split( Surface s, WLine line, GPoint cut )
  {
    Console.writeln( "begin split of " + line);

    // split the edge.
    cut.x += -2;
    cut.y += -2;
    WLine l = (WLine)line.clone();
    l.setTail( cut );

    HashSet set = new HashSet();
    set.add( l );

    cut.x += 4;
    cut.y += 4;
    l = (WLine)line.clone();
    l.setHead( cut );

    set.add( l );

    // do the replacement

    Console.writeln( "begin rep." );
    s.replaceWidget( line, set, true );

    Console.writeln( "end split" );
  }
  

  public boolean recognize_old( Surface s, Widget w )
  {
    WLine n = (WLine)w;
    GPoint h = n.getHead();
    GPoint t = n.getTail();

    boolean cut = false;

    // look for an edge to break
    Iterator e = s.getWidgetsIterator();
    while( e.hasNext() )
      {
	Object o = e.next();
	if ( o instanceof WLine )
	  {
	    WLine ed = (WLine)o;
	    if ( ( ed.includes( h, BREAK ) || ed.includes( t, BREAK ) )
		 && !n.includes( ed.getHead(), BREAK )
		 && !n.includes( ed.getTail(), BREAK ) )
	      {
		Console.writeln( "Going to cut " + ed );
		cut = true;

		// split the edge.
		GSegment g1 = ed.getLine();
		GPoint inter = g1.getIntersection( n.getLine() );
		WLine l = new WLine( ed.getHead(), inter );
		s.addWidget( l );

		inter.x += 4;
		inter.y += 4;
		l = new WLine( inter, ed.getTail() );
		s.addWidget( l );

		// kill old edge
		s.removeWidget( ed );
	      }
	  }
      }

    // see if we get broken
    e = s.getWidgetsIterator();
    while( e.hasNext() )
      {
	Object o = e.next();
	if ( o instanceof WLine )
	  {
	    WLine ed = (WLine)o;
	    h = ed.getHead();
	    t = ed.getTail();
	    if ( ( n.includes( h, BREAK ) || n.includes( t, BREAK ) )
		 && !ed.includes( n.getHead(), BREAK )
		 && !ed.includes( n.getTail(), BREAK ) )
	      {
		Console.writeln( "Going to self-cut " + n );
		cut = true;

		// split the edge.
		GSegment g1 = n.getLine();
		GPoint inter = g1.getIntersection( ed.getLine() );
		WLine l = new WLine( n.getHead(), inter );
		s.addWidget( l );

		inter.x += 4;
		inter.y += 4;
		l = new WLine( inter, n.getTail() );
		s.addWidget( l );

		// kill old main edge
		s.removeWidget( n );

		return true;
	      }
	  }
      }
    
    // never interrupt, just cut and move on.
    return false;

  } // end recognize_old

  

  
  public Iterator getInputTypes()
  {
    Vector v = new Vector();
    
    v.addElement( "rec.core.WLine" );
    v.addElement( "rec.house.Wall" );
    
    return v.iterator();
  }

  public Iterator getOutputTypes() 
  {
    return getInputTypes();
  }


}
