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

// -*-Mode: Java-*- 
// $Id: SquiggleArrowRecognizer.java,v 1.6 2003/03/06 00:40:47 moltmans Exp $
// SquiggleArrowRecognizer.java -- 
// Author: Michael Oltmans <moltmans@ai.mit.edu> 
// Created: <Tue Oct 26 18:06:29 1999> 
// Time-stamp: <2001-09-10 18:18:04 moltmans> 
package rec.core.recognizers;

import java.util.*;

import rec.util.*;
import rec.geo.*;
import rec.sys.*;
import rec.meche.Estimator;
import rec.core.widgets.*;

public class SquiggleArrowRecognizer extends Recognizer
{

  private boolean isArrowhead( Surface s, Squiggle squiggle,
			       WLine l1, WLine l2 )
  {
    GSegment s1 = l1.getLine();
    GSegment s2 = l2.getLine();
    
    if( Estimator.isSameSize( s1.size(), s2.size() )
	&& Estimator.arePerpendicular( s1, s2, 30.0 )
	&& ( squiggle.getLength() > ( s1.size() * 2.0 ) ) )
    {

      GPoint c = Estimator.connects( s1, s2, 20.0 );

      if( c != null ) {
	WSquiggleArrow wsa = null;
	GPoint first = squiggle.getFirstPoint();
	GPoint last  = squiggle.getLastPoint();

	if ( first.includes( c, 20 ) )
	  wsa = new WSquiggleArrow( squiggle, first, l1.size() );
	else if ( last.includes( c, 20 ) )
	  wsa = new WSquiggleArrow( squiggle, last, l1.size() );
	else {
	  //	  Console.writeln( "** Neither end is included" );
	  return false;
	}
	

	s.removeWidget( squiggle );
	s.removeWidget( l1 );
	s.removeWidget( l2 );

	s.addWidget( wsa );
	return true;
      }
      //      Console.writeln( "** The 2 lines don't connect" );
    }
    else {
//        Console.writeln( "** same size: " + Estimator.isSameSize( s1.size(), s2.size() ) );
//        Console.writeln( "** perp = " +  Estimator.arePerpendicular( s1, s2 ) );
//        Console.writeln( "** sq.size = " + squiggle.getLength() );
//        Console.writeln( "** s1.size * 2 = " + s1.size() * 2 );
    }
    
    
    return false;
  }
  
  
//    private boolean findArrow( Surface s, Squiggle squig )
//    {
//      GeometryCalculator gc = new GeometryCalculator( s );
//      Vector vect = new Vector( gc.getVisibleWidgets() );

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

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

//        if( vw1 instanceof WLine && !vw1.equals( l ) ) {

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

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

//  	  if( vw2 instanceof WLine &&
//  	      !vw2.relatedTo( squig ) &&
//  	      !vw2.relatedTo( vw1 ) )
//  	  {	      
//  	    if ( isArrowhead( squigg, (WLine)vw1, (WLine)vw2) ) {
//  	      return true;
//  	    }
//  	  }
//  	}
//        }
//      }
    
//      return( false );
//    }

  private boolean findArrow( Surface s, WLine line )
  {
    GeometryCalculator gc = new GeometryCalculator( s );
    Vector vect = new Vector( gc.getVisibleWidgets() );

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

      if( vw1 instanceof Squiggle && !vw1.relatedTo( line ) ) {
	Squiggle squigg = (Squiggle)vw1;

	//	Console.writeln( "** Got a squiggle" );

	if ( !line.includes( squigg.getFirstPoint(), 20 ) &&
	     !line.includes( squigg.getLastPoint(), 20 ) )
	{
	  //	  Console.writeln( "** Neither end is near" );

	  continue;
	}
		  
	for( int j = 0; j < vect.size(); ++j ) {
	  Widget vw2 = (Widget)vect.elementAt( j );

	  if( vw2 instanceof WLine &&
	      !vw2.equals( line ) &&
	      !vw2.relatedTo( squigg ) )
	  {
	    //	    Console.writeln( "** Found a second line!" );
	    
	    if ( isArrowhead( s, squigg, line, (WLine)vw2) ) {
	      return true;
	    }
	  }
	}
      }
    }
    
    return( false );
  }

  
  public boolean recognize( Surface s, Widget w )
  {
//      if ( w instanceof rec.sys.Squiggle ) {
//        return findArrow( (Squiggle)w );
//      }

    //    Console.writeln( "==================================================" );
    //    Console.writeln( "** working on: " + w );

    
    if ( w instanceof WLine ) {
      return findArrow( s, (WLine)w );
    }
    else {
      Assert.error( "Unknown type in CircleRecognizer: " + w );
      return( false );
    }
  }

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

    //    v.addElement( "rec.sys.Squiggle" );
    v.addElement( "rec.core.widgets.WLine" );

    return( v.iterator() );
  }

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

    v.addElement( "rec.core.widgets.WSquiggleArrow" );

    return( v.iterator() );
  }
}

