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

package rec.simulate.recognizers;

import rec.geo.*;
import java.util.*;
import java.awt.*;
import java.awt.geom.*;
import rec.util.*;
import rec.sys.*;
import rec.core.widgets.*;
import rec.meche.Estimator;
import rec.simulate.widgets.*;
import rec.simulate.*;
import edu.mit.sketch.geom.*;

public class SimTorqueRecognizer extends Recognizer
{
    public SimTorqueRecognizer()
    {
    }
    
    public boolean recognize( Surface s, Widget w )
    {
	boolean headpoint = false;
	boolean tailpoint = false;

	WLine line1 = null;
	WLine line2 = null;
	WToolkitArc arc = null;

	if (w instanceof WLine){

	    line1 = (WLine) w;

	    GeometryCalculator gc = new GeometryCalculator(s);
	    Iterator it = gc.getVisibleWidgets().iterator();
	    
	    while(it.hasNext()){
		VisibleWidget vw1 = (VisibleWidget)it.next();

		if (vw1 instanceof WToolkitArc){

		    arc = (WToolkitArc) vw1;

		    if(arc.getHeadPoint().includes(line1.getHead(), 15) ||
		       arc.getHeadPoint().includes(line1.getTail(), 15)){
			headpoint = true;
		    }
		    		    
		    else if(arc.getTailPoint().includes(line1.getHead(), 15) ||
			    arc.getTailPoint().includes(line1.getTail(), 15)){
			tailpoint = true;
		    }
		}
	    }
	}    
			
	else if(w instanceof WToolkitArc){
	    arc = (WToolkitArc) w;
	    
	    GeometryCalculator gc = new GeometryCalculator(s);
	    Iterator it = gc.getVisibleWidgets().iterator();
	    
	    while(it.hasNext()){
		VisibleWidget vw1 = (VisibleWidget)it.next();
		
		if (vw1 instanceof WLine){
		    
		    line1 = (WLine) vw1;
		   		    
		    if(arc.getHeadPoint().includes(line1.getHead(),15) ||
		       arc.getHeadPoint().includes(line1.getTail(),15)){
			headpoint = true;
		    }
		    
		    else if(arc.getTailPoint().includes(line1.getHead(),15) ||
			    arc.getTailPoint().includes(line1.getTail(),15)){
			tailpoint = true;
		    }
		}
	    }
	}

	else{
	    ///Should never happen
	    return false;
	}
		    
	if(headpoint || tailpoint){
	    
	    GeometryCalculator gc2 = new GeometryCalculator(s);
	    Iterator it2 = gc2.getVisibleWidgets().iterator();
	    
	    while(it2.hasNext()){
		VisibleWidget vw2 = (VisibleWidget)it2.next();
		
		if (vw2 instanceof WLine &&
		    !vw2.equals(line1)){
		    

		    line2 = (WLine) vw2;

		
				    
		    if((headpoint && 
			(arc.getHeadPoint().includes(line2.getHead(), 15)
			 || arc.getHeadPoint().includes(line2.getTail(), 15))) || 
		       (tailpoint &&
			(arc.getTailPoint().includes(line2.getHead(), 15)
			 || arc.getTailPoint().includes(line2.getTail(), 15)))){
			
			if(testConstraints(arc, line1, line2, headpoint, tailpoint)){
			    
			    boolean clockwise = false;

			    if (headpoint && !arc.getClockwise() ||
				tailpoint && arc.getClockwise()){
				//System.out.println("CLOCKWISE");
				clockwise = true;
			    }
			    else{
				//System.out.println("COUNTER CLOCKWISE");
			    }

			    SimulateSurface SimS = (SimulateSurface) s;
			    
			    WSimTorque torque = SimS.makeSimTorque(arc, 
								   line1, 
								   line2, 
								   clockwise);
			    
			    HashSet set = new HashSet();
			    set.add(arc);
			    set.add(line1);
			    set.add(line2);
			    
			    s.replaceWidget(set, torque, true);
			    
			    return true;
			}
		    }
		}
	    }
	}
	return false;
    }
    
    private boolean testConstraints (WToolkitArc arc, 
				     WLine line1, 
				     WLine line2, 
				     boolean headpoint,
				     boolean tailpoint){

	if(!Estimator.arePerpendicular(line1.getLine(),line2.getLine())){
	    return false;
	}
	
	GPoint connectorPoint1;
	GPoint connectorPoint2;

	

	if(headpoint){

	    if(arc.getHeadPoint().includes(line1.getHead(), 15)){
		connectorPoint1 = line1.getTail();
	    }
	    else{
		connectorPoint1 = line1.getHead();
	    }

	    if(arc.getHeadPoint().includes(line2.getHead(), 15)){
		connectorPoint2 = line2.getTail();
	    }
	    else{
		connectorPoint2 = line2.getHead();
	    }
	}

	else if (tailpoint){
	    if(arc.getTailPoint().includes(line1.getHead(), 15)){
		connectorPoint1 = line1.getTail();
	    }
	    else{
		connectorPoint1 = line1.getHead();
	    }

	    if(arc.getTailPoint().includes(line2.getHead(), 15)){
		connectorPoint2 = line2.getTail();
	    }
	    else{
		connectorPoint2 = line2.getHead();
	    }
	}
	else{
	    //shouldn't happen
	    return false;
	}

	Line connector = new Line(connectorPoint1.getX(),
				  connectorPoint1.getY(),
				  connectorPoint2.getX(),
				  connectorPoint2.getY());

	connector.paint();

	boolean returnme = connector.touches(arc.getArc().getToolkitArc());

	return returnme;
    }
    
    public Iterator getInputTypes()
    {
	Vector v = new Vector();
	
	v.addElement( "rec.core.widgets.WLine" );
	v.addElement( "rec.core.widgets.WToolkitArc");
	
	return( v.iterator() );
    }
    
    public Iterator getOutputTypes()
    {
	Vector v = new Vector();
	
	v.addElement( "rec.simulate.widgets.WSimTorque" );
	
	return( v.iterator() );
    }
    
}
