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

///////////////////////////////////////////////////////////////////////////////
//
// FILE:	MoveRecognizer.java
//
// AUTHOR:      Luke Weisman
//              luke@ai.mit.edu
//
//              Manoj D. Muzumdar
//		archon@ai.mit.edu
//
// DATE:	06-XX-98
//
// COPYRIGHT:	Massachusetts Institute of Technology
//		All rights reserved.
//
// PURPOSE:	Drawing recognition
//
// HISTORY:     09-XX-98 archon
//              Modified to fit with new recognition model
//
//              11-15-98 archon
//              Now aware of new rec.geo package
//
///////////////////////////////////////////////////////////////////////////////

package rec.core.recognizers;

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


public class MoveRecognizer extends FastRecognizer
{
  // the thing being moved (null if none)
  protected VisibleWidget movie;
  protected double m_Offset_X;
  protected double m_Offset_Y;
  
  public MoveRecognizer()
  {
  }

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

  /**
   * This is called with every point added to the stroke.  If the 
   * rec returns WANT it gets full control of all added points,
   * UNSURE makes no comment, and DONT_WANT stops all calls.
   * 
   * DONT_WANT is not absolutely needed.  UNSURE works as well.
   */
  public int want( Surface s, rec.sys.Squiggle st, boolean ending )
  {
    if( movie == null ) {

      GPoint p = st.getFirstPoint();
	
      GeometryCalculator calc = new GeometryCalculator( s );
      VisibleWidget vw = calc.findSelectedOnSurface( p );

      movie = vw;
      if( vw == null ) {
	//Console.writeln( "nothing selected." );
	return( DONT_WANT );
      }
      else {
	//Console.writeln( vw + " selected-- going to take it" );
	// get the offset so we don't always move from the middle
	Console.writeln( movie + " is starting centered at " +
			 movie.getLocation().getCenter() );
	m_Offset_X = st.getFirstPoint().x -
	  movie.getLocation().getCenter().x;
	m_Offset_Y = st.getFirstPoint().y -
	  movie.getLocation().getCenter().y;
      }
    }
    
    if( st.getNumberOfPoints() > 5 )
      return( WANT );
    else
      return( UNSURE );
  }

  public void reset()
  {
    movie = null;
  }

  public boolean recognize( Surface s, rec.sys.Squiggle st, boolean ending )
  {
    GPoint prevLocation = movie.getLocation().getCenter();

    GPoint actual_move = new GPoint( st.getLastPoint().x - m_Offset_X,
				     st.getLastPoint().y - m_Offset_Y );
    Console.writeln( "The last point is: " + st.getLastPoint() );
    Console.writeln( "The actual move is: " + actual_move );

    Collection anc_and_me = movie.getAncestors();
    anc_and_me.add( movie );
    
    Iterator it = anc_and_me.iterator();
    while ( it.hasNext() ) {
      Object o = it.next();
      if ( o instanceof VisibleWidget ) {
	DoTransition t = new MoveTransition( s,
					     (VisibleWidget)o,
					     actual_move );
	t.doDo();
	s.addTransition( t );
	Console.writeln( "moving " + o );
      }
    }  
    
    // i think that if we decide that the fast move is not what we
    // want to do we are going to have to undo lots of stuff from the
    // transition recorder anyway.
    // i guess we are just assume the "old-style" recognition for fast
    // recognition so make the squiggle die.
    // also, we need to kill the children of the object moved, and
    // redo recognition, reasoning and resolution on the new position
    // of the object.
    if ( ending ) {
      
      DoTransition dt = new DieTransition( s, st );
      st.addToSuitcase( dt );
    }
      
    // now we have nothing in the widget pool from the action.
    
    return( true );
  }

  public Iterator getOutputTypes()
  {
    return ( new Vector() ).iterator();
  }
}

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