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

package rec.simulate;
// -*-Mode: Java-*- 
// SimulatorRegistry.java -- 
// Author: Christine Alvarado <calvarad@ai.mit.edu> 
// Maintainer: Christine Alvarado <calvarad@ai.mit.edu> 
// Version: 
// Created: <Wed Mar 10 17:00:26 1999> 
// Time-stamp: <2002-04-10 17:50:47 moltmans> 
// Keywords: 

// This class is similar to a WidgetRegistry, but it only keeps track 
// of widgets which are of type SimulatableObject (or WMSimObject, possibly)
// It is really just a dummy class for now.  Later it will do the calculation
// of relations between objects.  It will also somehow hold environment 
// settings like gravity and the like.  -cja

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

// should rename all these classes (ie the sim registries) to sim pools
//since they are now pools, but i won't right now because i am being lazy
public abstract class SimulatorRegistry extends WidgetPool
{
  
  

  public SimulatorRegistry( )
  {
    super( );
    m_gravity = false;
  }

  ///////////////////////////////////////////////////////////////////////////
  // functions to create objects.  Used for subclasses
  public abstract WSimRectangle makeRectangle( WRectangle r );
  public abstract WSimQuadrilateral makeQuadrilateral( WQuadrilateral q );  
  public abstract WSimCircle makeCircle( WCircle c );
  public abstract WSimTriangle makeTriangle( WTriangle t );
  public abstract WSimSpring makeSpring( WMSpring spr );
  public abstract WSimPulley makePulley( List wheels, List ropes );
  public abstract WSimPolygon makePolygon( PolygonInfo pi );
  public abstract WSimPolygon makePolygon( WPolygon poly );
  public abstract WSimForce makeForce( WMForce f );
  public abstract WSimAnchor makeAnchor( GPoint center, double size );
  public abstract WSimMotor makeMotor(GPoint center);
  public abstract WSimGear makeGear(WCircle circle);
  public abstract WSimGearTrain makeGearTrain(WSimGear[] gears, 
					      WSimGearTrain[] trains, 
					      WSimGear newGear, 
					      boolean singleCircles);
  public abstract WSimTorque makeTorque(WToolkitArc arc, WLine line1, 
					WLine line2, boolean clockwise);
  public abstract WSimSpringDamper makeSpringDamper(GSegment base, 
						    boolean damperup);
  public abstract WSimPinJoint makePinJoint( WSimCircle c );
  public abstract WSimDamper makeDamper( GSegment s );
  public abstract WSimRod makeRod( WLine l );
  public abstract WSimRope makeRope( WComplex c );
  public abstract WSimRope makeRope( WLine l );
  public abstract WSimRotationalDamper makeRotationalDamper(GPoint center);
  public abstract WSimRotationalSpring makeRotationalSpring(GToolkitSpiral spiral);

///////////////////////////////////////////////////////////////////////////
  public abstract GPoint convert( GPoint c );
  public abstract double convert( double x );
  
  // in the future there will be a function here to do on the spot recognition
  // of mechanical parts when the "run" button is clicked.
  // for now here is a function which takes all the widgets it sees on the
  // surface and attaches them to any others which exist.
  // for now only SimParts can be connected to SimBodies
  public void attach( Surface s )
  {
    
    boolean att;
    Iterator it = s.getSurfacePoolIterator();

    // first remove all the old attachments
    while( it.hasNext() ) {
      Widget p = (Widget)it.next();
      // check to see if this is a WSimPart
      if( p instanceof WSimConstraint ) {
	((WSimConstraint)p).detach();
      }
      if( p instanceof WSimBody ) {
	((WSimBody)p).clearConstraints();
      }
    }

    // now redetermine the attachments and constraints
    it = s.getSurfacePoolIterator();
    while( it.hasNext() ) {
      Widget p = (Widget)it.next();
      // check to see if this is a WSimPart
      if ( p instanceof WSimConstraint ) {
	// if it is, got through all the other widgets to see if this one
	// should be attached to them.
	Iterator it2 = s.getSurfacePoolIterator();
	while ( it2.hasNext() ) {
	  Widget b = (Widget)it2.next();
	  if ( b instanceof WSimBody ) {
	    // attach checks to see if b should be 
	    //attached to p and then attaches it if necessary
	    att = ((WSimConstraint)p).attach( (WSimBody)b );
	    if( att ) {
	      ((WSimBody)b).addConstraint( (WSimConstraint)p );
	    }
	  }
	}
      }
    }
  }

  public boolean isGravityOn()
  {
    return m_gravity;
  }
  
  public void setGravity( Surface s ) 
  {
    m_gravity = false;
    // go through and if you see and unattached arrow pointing down, it
    // means gravity is on
    Iterator it = s.getSurfacePoolIterator();
    while( it.hasNext() ) {
      Widget w = (Widget)it.next();
      if ( w instanceof WSimForce ) {
	WSimForce f = (WSimForce)w;
	double lower = ((1.5 * Math.PI) - ( Math.PI * 2 * (5.0 / 360.0) ));
	double upper = ((1.5 * Math.PI) + ( Math.PI * 2 * (5.0 / 360.0) ));
	if ( ((1.5 * Math.PI) - ( Math.PI*2*(5.0 / 360.0) ) < f.angle() ) &&
	     ((1.5 * Math.PI) + ( Math.PI*2*(5.0 / 360.0) ) > f.angle() ) &&
	     ( f.numAttached() == 0 ) ) {
	  Console.writeln( "Turning Gravity on" );
	  m_gravity = true;
	  f.forceIsGravity( true );
	} 
	else {
	    f.forceIsGravity( false );
	}
      }
    }
  }
  
  public abstract void load( Surface s );

  public abstract void shutdown();

  ///////////////////////////////////////////////////////////////////////////
  boolean m_gravity;
  

}


