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

package rec.meche;

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

public class LooseForceRecognizer extends ForceRecognizer
{

  public static WMForce isForce( WLine l1, WLine l2, WLine l3 )
  {
    GSegment s1 = new GSegment( l1.getHead(), l1.getTail() );
    GSegment s2 = new GSegment( l2.getHead(), l2.getTail() );
    GSegment s3 = new GSegment( l3.getHead(), l3.getTail() );

    
    GSegment a1 = null;
    GSegment a2 = null;
    GSegment body = null;


    if( Estimator.isSameSize( s1.size(), s2.size() )
	&& s3.size() > (s1.size() * 2) ) {
      a1 = s1;
      a2 = s2;
      body = s3;
    }
    else if( Estimator.isSameSize( s2.size(), s3.size() )
	     && s1.size() > (s2.size() * 2) ) {
      a1 = s2;
      a2 = s3;
      body = s1;
    }
    else if( Estimator.isSameSize( s1.size(), s3.size() )
	     && s2.size() > (s1.size() * 2.0) ) {
      a1 = s1;
      a2 = s3;
      body = s2;
    }

    // Return if initial tests fail.

    else {
      //Console.writeln( "d: " + s1.size() + " " + s2.size() + " " + s3.size() );

      return( null );
    }

    GPoint c1 = Estimator.connects( body, a1, 20.0 );
    GPoint c2 = Estimator.connects( body, a2, 20.0 );

    if( c1 != null && c2 != null 
	&& (Geometry.distance( c1, c2 ) < 10 ) )
      {

      if( c1.equals( body.getHeadPoint() ) )
	return( new WMForce( body.getMidpoint(),
			     Geometry.angle( body.getTailPoint(),
					     body.getHeadPoint() ),
			     body.size(),
			     null ) );

      if( c1.equals( body.getTailPoint() ) )
	return( new WMForce( body.getMidpoint(),
			     Geometry.angle( body.getHeadPoint(),
					     body.getTailPoint() ),
			     body.size(),
			     null ) );
    }
    else
      {
	//Console.writeln( "possible match, failed to connect." );
	// Incorrect connection.
	return( null );
      }

    Assert.check( false, "got null when should have connected." );
    return null;
  }



  public boolean recognize( Surface s, Widget w )
  {
    WLine l = (WLine)w;

    GeometryCalculator gc = new GeometryCalculator( s );
     
    Vector vect = new Vector();
    Iterator it = gc.getVisibleWidgets().iterator();

    // prune to smaller set so we do less work.
    while( it.hasNext() )
      {
	Widget w1 = (Widget)it.next();

	if ( ( w1 instanceof WLine )
	     && ( ((WLine)w1).overlaps( l ) )
	     && ( !w1.equals( l ) ) )
	  vect.addElement( w1 );
      }

    for( int i = 0; i < vect.size(); ++i ) {

      Widget vw1 = (Widget)vect.elementAt( i );

	for( int j = 0; j < vect.size(); ++j ) {

	  Widget vw2 = (Widget)vect.elementAt( j );

	  if( !vw2.equals( vw1 ) ) {
              
	    WMForce wf = isForce( l, (WLine)vw1, (WLine)vw2 );

	    if( wf != null ) {

	      s.removeWidget( l );
	      s.removeWidget( vw1 );
	      s.removeWidget( vw2 );

	      s.addWidget( wf );

	      return( true );
	    }
	  }
	}
    }

    return( false );
  }


}


