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

package rec.simulate.widgets;

import rec.geo.*;
import rec.sys.*;
import rec.core.widgets.*;
import rec.meche.WMSpring;
import rec.simulate.widgets.*;
import rec.simulate.widgets.wm.*;
import java.util.*;
import rec.util.*;

public abstract class WSimSpringDamper extends WSimConstraint
{
  
    public WSimSpringDamper(GSegment base, boolean damperUp)
    {
	setDefaultColor( "springdamper", "sim_constraint" );
	setEnglishName( "SpringDamper" );
	m_tailBody = null;
	m_headBody = null;

	m_Size = base.size();

	GPoint damperEndOne;
	GPoint damperEndTwo;
	GPoint springCenter;

	if((damperUp && 
	    (base.getTailPoint().getX() < base.getHeadPoint().getX())) ||
	   (!damperUp &&
	    (base.getTailPoint().getX() > base.getHeadPoint().getX())))
	{
	    damperEndOne = new GPoint(-.3 * m_Size, .1 * m_Size);
	    damperEndTwo = new GPoint(.3 * m_Size, .1 * m_Size);
	    springCenter = new GPoint(0, -.1 * m_Size);
	}
	else{
	    damperEndOne = new GPoint(-.3 * m_Size, -.1 * m_Size);
	    damperEndTwo = new GPoint(.3 * m_Size, -.1 * m_Size);
	    springCenter = new GPoint(0, .1 * m_Size);
	}

	WMSimSpring spring = new WMSimSpring(new WMSpring(springCenter, 0, 
							  .6 * m_Size, null)); 

	WMSimDamper damper  = new WMSimDamper(new GSegment(damperEndOne, 
							   damperEndTwo));
	
	GShape SpringComponents[] = spring.m_Components;
	GShape DamperComponents[] = damper.m_Components;

	int numComponents = SpringComponents.length + DamperComponents.length + 4;

	//Components:
	// 4 sides
	// 11 spring pieces
	// 4 damper pieces
	// = 19

	m_Components = new GShape[numComponents];

	// The segments that make the end points - 1/5th the size of the base
	m_Components[0] = new GSegment( new GPoint(-.3 * m_Size, 0),
					new GPoint(-.5 * m_Size, 0));
	m_Components[1] = new GSegment( new GPoint(.5 * m_Size, 0),
					new GPoint(.3 * m_Size, 0));

	// The bars that cross the end bars and connect to the spring and damper
	m_Components[2] = new GSegment( new GPoint(-.3 * m_Size, .1 * m_Size),
					new GPoint(-.3 * m_Size, -.1 * m_Size));
	m_Components[3] = new GSegment( new GPoint(.3 * m_Size, .1 * m_Size),
					new GPoint(.3 * m_Size, -.1 * m_Size));

	int i = 4;
	int j = 0;

	while (j < SpringComponents.length){
	    m_Components[i] = SpringComponents[j];
	    i++;
	    j++;
	}

	j = 0;

	while(j < DamperComponents.length){
	    m_Components[i] = DamperComponents[j];
	    i++;
	    j++;
	}

	rotate( new GPoint( 0.0, 0.0 ), -1 * base.getAngle() );
    
	move( base.getMidpoint() );
	
	m_Name = "SpringDamper" + getId();
	
    }

    public boolean attach(WSimBody b)
    {
	if ( ( m_tailBody != null ) && ( m_headBody != null ) ) {
	    Console.writeln( "Cannot attach to body" + b.getName() );
	    return false;
	}
	// check to see if one of the ends is touching or 
	// inside the body in question.
	
	// the offset is set to 10, meaning the end must be 
	//close to the body

	if ( m_tailBody == null ) {
	    if ( b.includes( getTailPoint(), 10 ) || 
		 b.contains( getTailPoint(), 0 ) ) {
		m_tailBody = b;
		return true;
	    }
	}
	if ( m_headBody == null ) {
	    if ( b.includes( getHeadPoint(), 10 ) || 
		 b.contains( getHeadPoint(), 0 ) ) {
		m_headBody = b;
		return true;
	    }
	}

	return false;

    }

    public GPoint getHeadPoint(){
	//component zero is one end
	return ((GSegment)m_Components[1]).getHeadPoint();
    }

    public GPoint getTailPoint(){
	//component one is the other end
	return ((GSegment)m_Components[0]).getTailPoint();
    }

    public GPoint getAttachmentPoint(WSimBody b)
    {
	if( b.equals( m_tailBody ) )
	    return getHeadPoint();
	else if( b.equals( m_headBody ) )
	    return getTailPoint();
	else
	    return null;
    }
 
    public void detach()
    {
	m_tailBody = null;
	m_headBody = null;
    }

    public int numAttached()
    {
	int count = 0;

	if( m_tailBody != null )
	    count++;
	if( m_headBody != null )
	    count++;
	return count;
    }

    public List getBodies()
    {
	List list = new ArrayList( numAttached() );
	if( m_tailBody != null )
	    list.add( m_tailBody );
	if( m_headBody != null )
	    list.add( m_headBody );
	return list;
    }

    protected WSimBody m_tailBody;
    protected WSimBody m_headBody;
}



