// $Id: ManipulateWheel.java,v 1.1 2004/02/25 17:24:17 cadlerun Exp $
// ManipulateWheel.java -- 
// Author: Aaron Adler <cadlerun@fracas.ai.mit.edu> 
// Copyright: Copyright (C) 2002 by Aaron Adler 
// Created: <Sun Jan  4 14:58:07 2004> 

package rec.multi;

import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.ArrayList;

import java.awt.Rectangle;

import rec.sys.Widget;
import rec.simulate.widgets.wm.WMSimCircle;
import rec.simulate.widgets.wm.WMSimPinJoint;
import rec.simulate.widgets.WSimBody;
import rec.simulate.widgets.WSimPinJoint;
import rec.geo.GPoint;

import edu.mit.tools.watch.Logging;
import org.apache.log4j.Logger;

/***
 * This class takes a set of wheels (which is a set of Pin Joints
 * and circles) and has methods for various commands to make
 * the wheels identical
 ***/

public class ManipulateWheel {
  private static Logger LOG = Logging.SPEECH;

  Set m_wheels;
  ArrayList m_circles = new ArrayList();
  ArrayList m_pinJoints = new ArrayList();
  
  public ManipulateWheel(Set wheels) {
    // initializes the set of wheels and the lists of circles and pin
    // joints. the indices in the lists correspond to the same wheel
    
    m_wheels = wheels;
    Iterator w = m_wheels.iterator();

    while(w.hasNext()) {
      Set wheel = (Set)w.next();
      Iterator w2 = wheel.iterator();
      while (w2.hasNext()) {
	Widget a = (Widget)w2.next();
	if (a instanceof WMSimCircle) {
	  m_circles.add(a);
	  LOG.debug("adding circle in manipulate wheel");
	}
	if (a instanceof WMSimPinJoint) {
	  m_pinJoints.add(a);
	  LOG.debug("adding pin joint in manipulate wheel");
	}
      }
    }
  }

  public void makeIdentical() {
    // do this in two step... first resize the circles,
    // then we need to move the pin circles to the right location.
    // TODO: not sure why we use rectangular bounds instead of circle radius
    
    LOG.debug("making wheels identical");
    
    Iterator cirIt = m_circles.iterator();
    double numWheels = m_circles.size();
    
    double totalW = 0.0;
    double totalH = 0.0;

    // do the circle and rod calculations
    while (cirIt.hasNext()) {
      //circle calculations
      WSimBody w = (WSimBody)cirIt.next();
      Rectangle bounds = w.getBounds();
      totalW = totalW + bounds.getWidth();
      totalH = totalH + bounds.getHeight();
    }

    double wScale = totalW / numWheels;
    double hScale = totalH / numWheels;
    
    // now rescale the shapes
    cirIt = m_circles.iterator();
    Iterator pinIt = m_pinJoints.iterator();
    
    while (cirIt.hasNext()) {
      //scale the circle
      WSimBody w = (WSimBody) cirIt.next();
      Rectangle bounds = w.getBounds();
      // we can only scale in one direction at the moment --
      // not sure what to do about that
      double cScaleFactor = wScale / bounds.getWidth();
      w.resize(cScaleFactor);

      // now we just need to move the scaled circle so that
      // the center is the center of the pin joint

      WSimPinJoint pin = (WSimPinJoint) pinIt.next();
      GPoint pinCenter = pin.getLocation().getCenter();

      // move the circle to the pin center
      w.move(pinCenter);
      
      // update the surface to see the results
      w.getSurface().getScreen().repaint();
    }    
  }

  
}
