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

////////////////////////////////////////////////////////////////////////////////
//
// FILE:	BallAndSocketRecognizer.java
//
// AUTHOR:	Manoj D. Muzumdar
//		archon@ai.mit.edu
//
// DATE:	April 99
//
// COPYRIGHT:	Massachusetts Institute of Technology
//		All rights reserved.
//
// PURPOSE:	Ball and socket recognition
//
// HISTORY:     April 99  archon  created
//
////////////////////////////////////////////////////////////////////////////////

package rec.meche;

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

public class BallAndSocketRecognizer extends Recognizer
{
  public static WMBallAndSocket isBallAndSocket( WMBall ball, WMSocket socket )
  {
    if( ball.size() > 2.0 * socket.size()
	|| 2.0 * ball.size() < socket.size() )
      return( null );

    if( !( Geometry.distance( ball.getJoint(), socket.getJoint() ) < 15.0 ) )
      return( null );

    // Connect the ball and socket.

    return( new WMBallAndSocket( ball, socket ) );
  }

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

  public BallAndSocketRecognizer()
  {
  }

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

  public boolean recognize( Surface s, Widget w )
  {
    GeometryCalculator gc = new GeometryCalculator( s );

    Collection tmp = gc.getVisibleWidgets();
    Iterator it = tmp.iterator();

    if( tmp.size() < 2 )
      return( false );

    if( w instanceof WMBall ) {

      while ( it.hasNext() ) {

	VisibleWidget vw1 = (VisibleWidget)it.next();

	if( vw1 instanceof WMSocket ) {

	  WMBallAndSocket part = isBallAndSocket( (WMBall)w, (WMSocket)vw1 );

	  if( part != null ) {

	    s.removeWidget( w );
	    s.removeWidget( vw1 );

	    s.addWidget( part );

	    return( true );
	  }
	}
      }
    }


    if( w instanceof WMSocket ) {
      
      it = tmp.iterator();

      while ( it.hasNext() ) {

	Widget vw1 = (Widget)it.next();

	if( vw1 instanceof WMBall ) {

	  WMBallAndSocket part = isBallAndSocket( (WMBall)vw1, (WMSocket)w );

	  if( part != null ) {

	    s.removeWidget( w );
	    s.removeWidget( vw1 );

	    s.addWidget( part );

	    return( true );
	  }
	}
      }
    }

    return( false );
  }

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

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

    v.addElement( "rec.meche.WMBall" );
    v.addElement( "rec.meche.WMSocket" );

    return( v.iterator() );
  }

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

    v.addElement( "rec.meche.WMBallAndSocket" );

    return( v.iterator() );
  }
}

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