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

// -*-Mode: Java-*- 
// $Id: LeverAttachmentForceRule.java,v 1.5 2005/02/17 21:41:00 moltmans Exp $
// LeverAttachmentForceRule.java -- 
// Author: Michael Oltmans <moltmans@ai.mit.edu> 
// Created: <Fri May 26 15:55:13 2000> 
// Time-stamp: <2005-02-16 14:03:40 moltmans> 
package rec.annotate.rules;

import rec.annotate.facts.*;
import java.util.*;
import rec.util.*;
import rec.tms.*;
import rec.sys.*;
import rec.geo.*;
import rec.simulate.widgets.*;

/**
 * 
 **/
public class LeverAttachmentForceRule extends AnnotateRule
{

  public LinkedList getTriggers() 
  {
    LinkedList triggers = new LinkedList();
    triggers.add( Type.GRAVITY );
    triggers.add( Type.LEVER );
    triggers.add( Type.ATTACHMENT );
    triggers.add( new String[] {Type.ROD,
				Type.PIN_JOINT,
				Type.PULLEY} );
    triggers.add( Type.BODY );
    return triggers;
  }

  public boolean match( LinkedList params ) 
  {
    if( params.size() < 3 )
      return true;

    Lever lever = (Lever)params.get(1);
    Attachment attach = (Attachment)params.get(2);
    if( !attach.getBodies().contains( lever.getBody() ) )
      return false;
    if( params.size() == 3 )
      return true;

    PartConstraint part = (PartConstraint)params.get(3);
    if( !attach.getPart().equals( part ) )
      return false;
    if( params.size() == 4 )
      return true;
	
    Body body = (Body)params.get(4);
    return ( !body.equals( lever.getBody() ) &&
	     attach.getBodies().contains( body ) );
  }

  private Force getForce( Lever lever, Body body, Attachment attach )
  {
    WSimBody b = body.getBody();
    WSimBody l = lever.getBody().getBody();
    double ydiff;


    if( attach.getPart() instanceof Pulley ) {
      Pulley pulley = (Pulley)attach.getPart();
      WSimPulley wpulley = pulley.getPulley();
      ydiff = ( l.getLocation().getCenter().getY() -
		wpulley.getFirstAnchorPoint().getY() );
    }
    else {
      ydiff = ( l.getLocation().getCenter().getY() -
		b.getLocation().getCenter().getY() );
    }

    return new Force( lever.getBody(),
		      attach.getAttachmentPoint( lever.getBody() ),
		      new GPoint( 0.0, ydiff ) );
  }
    
  public void run( Surface s, Notebook book, LinkedList params )
  {
    Lever lever = (Lever)params.get(1);
    Attachment attach = (Attachment)params.get(2);
    Body body = (Body)params.get(4);

    Force force = getForce( lever, body, attach );
    book.myassert( force, "LeverForceRule", params );
  }
}

