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

// -*-Mode: Java-*- 
// $Id: AnnotationMergeRecognizer.java,v 1.2 2003/03/06 00:40:43 moltmans Exp $
// AnnotationMergeRecognizer.java -- 
// Author: Michael Oltmans <moltmans@ai.mit.edu> 
// Created: <Thu Mar 16 14:25:20 2000> 
// Time-stamp: <2000-04-12 23:04:29 moltmans> 
package rec.annotate.recognizers;

import java.util.*;
import rec.sys.*;
import rec.util.*;
import rec.simulate.widgets.*;
import rec.annotate.*;
import rec.annotate.widgets.*;

/**
 * This class merges entities in annotations to map names
 **/
public class AnnotationMergeRecognizer extends Recognizer
{

  public boolean recognize( Surface s, Widget w )
  {
    //    DebugWindow.addLine( "DebugAnnotations", "Trying with: " + w );

    Annotation annotation = ((WAnnotation)w).getAnnotation();
    Annotation merged;
    WAnnotation candidate;

    WAnnotation foundWidget = null;
    Annotation foundMerged = null;
    boolean found = false;

    // get other potential annotation
    Iterator it = s.getLastNWidgets(1).iterator();

    while ( it.hasNext() ) {
      Widget o = (Widget)it.next();

      // must be a wannotation of the same type
      if ( !(o instanceof WAnnotation) &&
	   !o.isItA( w.getClass() ) )
	continue;

//        DebugWindow.addLine( "DebugAnnotations",
//  			   "  From iterator: " + o );

      // don't merge annotations derived from each other
      if (!w.relatedTo( o )) {
	candidate = (WAnnotation)o;

//    	DebugWindow.addLine( "DebugAnnotations",
//    			     "Trying to merge: " +
//    			     ((MovementAnnotation)candidate.getAnnotation()).describe() );
//      	DebugWindow.addLine( "MO",
//      			     "                 " + annotation.describe() );

	Annotation a = (Annotation)candidate.getAnnotation();

	// we want the first one to be the subclass
	if( a.getClass().isAssignableFrom( annotation.getClass() ) )
	  merged = annotation.merge( a );
	else
	  merged = a.merge( annotation );

//      	DebugWindow.addLine( "MO", "Merger = " + merged );

	if ( merged != null ) {
	  if ( found ) {
  	    DebugWindow.addLine( "Problems", "Multiple interpretations: " +
  				 annotation + " and " + candidate );
	    return false;
	  }
	  foundWidget = candidate;
	  foundMerged = merged;
	  found = true;
	}
      }
      else {
//  	DebugWindow.addLine( "DebugAnnotations", "  related to " + o );
      }
    }

    if ( found ) {
      s.removeWidget( w );
      s.removeWidget( foundWidget );
      s.addWidget( foundWidget.makeAnnotationWidget( foundMerged,
					 s.getAnnotationNotebook() ) );

      DebugWindow.addLine( "MO-Merge",
  			   "Possible merge of:\n" +
			   foundWidget.getAnnotation().describe() +
			   "\n" +
			   annotation.describe() );
      DebugWindow.addLine( "MO-Merge",
  			   "into: " +
			   foundMerged.describe() );
      return true;
    }
    
    return false;
  }

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

    v.addElement( "rec.annotate.widgets.WMovementAnnotation" );
    v.addElement( "rec.annotate.widgets.WLatchAnnotation" );

    return( v.iterator() );
  }

  public Iterator getOutputTypes()
  {
    Vector v = new Vector();
    v.addElement( "rec.annotate.widgets.WAnnotation" );

    return( v.iterator() );
  }
}


