// IMPORTED FROM PICCOLOX

package netmatch.piccolox;

import edu.umd.cs.piccolo.PCamera;
import edu.umd.cs.piccolo.PCanvas;
import edu.umd.cs.piccolo.PLayer;
import edu.umd.cs.piccolo.PRoot;
import edu.umd.cs.piccolo.util.PAffineTransform;
import edu.umd.cs.piccolo.util.PBounds;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.geom.Rectangle2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Iterator;

public class PDefaultScrollDirector implements PScrollDirector, PropertyChangeListener {

  protected PViewport viewPort;
  protected PScrollPane scrollPane;
  protected PCanvas view;
  protected PCamera camera;
  protected PRoot root;
  protected boolean scrollInProgress;

  public PDefaultScrollDirector() {
    scrollInProgress = false;
  }

  public void install(PViewport pviewport, PCanvas pcanvas) {
    scrollPane = (PScrollPane) pviewport.getParent();
    viewPort = pviewport;
    view = pcanvas;
    if(pcanvas != null) {
      camera = pcanvas.getCamera();
      root = pcanvas.getRoot();
    }
    if(camera != null)
      camera.addPropertyChangeListener(this);
    if(root != null)
      root.addPropertyChangeListener(this);
    if(scrollPane != null)
      scrollPane.revalidate();
  }

  public void unInstall() {
    viewPort = null;
    view = null;
    if(camera != null)
      camera.removePropertyChangeListener(this);
    if(root != null)
      root.removePropertyChangeListener(this);
    camera = null;
    root = null;
  }

  public Point getViewPosition(Rectangle2D rectangle2d) {
    Point point = new Point();
    if(camera != null) {
      PBounds pbounds = new PBounds();
      java.util.List list = camera.getLayersReference();
      PLayer player;
      for(Iterator iterator = list.iterator();iterator.hasNext();pbounds.add(player.getFullBoundsReference()))
        player = (PLayer) iterator.next();

      camera.viewToLocal(pbounds);
      pbounds.add(rectangle2d);
      point.setLocation((int) ((rectangle2d.getX() - pbounds.getX()) + 0.5D), (int) ((rectangle2d.getY() - pbounds.getY()) + 0.5D));
    }
    return point;
  }

  public Dimension getViewSize(Rectangle2D rectangle2d) {
    Dimension dimension = new Dimension();
    if(camera != null) {
      PBounds pbounds = new PBounds();
      java.util.List list = camera.getLayersReference();
      PLayer player;
      for(Iterator iterator = list.iterator();iterator.hasNext();pbounds.add(player.getFullBoundsReference()))
        player = (PLayer) iterator.next();

      if(!pbounds.isEmpty())
        camera.viewToLocal(pbounds);
      pbounds.add(rectangle2d);
      dimension.setSize((int) (pbounds.getWidth() + 0.5D), (int) (pbounds.getHeight() + 0.5D));
    }
    return dimension;
  }

  public void setViewPosition(double d, double d1) {
    if(camera != null && !scrollInProgress) {
      scrollInProgress = true;
      PBounds pbounds = new PBounds();
      java.util.List list = camera.getLayersReference();
      PLayer player;
      for(Iterator iterator = list.iterator();iterator.hasNext();pbounds.add(player.getFullBoundsReference()))
        player = (PLayer) iterator.next();

      PAffineTransform paffinetransform = camera.getViewTransform();
      paffinetransform.transform(pbounds, pbounds);
      PBounds pbounds1 = camera.getBoundsReference();
      pbounds.add(pbounds1);
      java.awt.geom.Point2D.Double double1 = new java.awt.geom.Point2D.Double(pbounds.getX() + d, pbounds.getY() + d1);
      camera.localToView(double1);
      double d2 = -(paffinetransform.getScaleX() * double1.getX() + paffinetransform.getShearX() * double1.getY());
      double d3 = -(paffinetransform.getShearY() * double1.getX() + paffinetransform.getScaleY() * double1.getY());
      paffinetransform.setTransform(paffinetransform.getScaleX(), paffinetransform.getShearY(), paffinetransform.getShearX(), paffinetransform.getScaleY(), d2, d3);
      camera.setViewTransform(paffinetransform);
      scrollInProgress = false;
    }
  }

  public void propertyChange(PropertyChangeEvent propertychangeevent) {
    boolean flag = "viewTransform" == propertychangeevent.getPropertyName();
    boolean flag1 = ("bounds" == propertychangeevent.getPropertyName() || "fullBounds" == propertychangeevent.getPropertyName()) && (propertychangeevent.getSource() == camera || propertychangeevent.getSource() == view.getRoot());
    if(flag || flag1)
      if(shouldRevalidateScrollPane())
        scrollPane.revalidate();
      else
        viewPort.fireStateChanged();
  }

  public boolean shouldRevalidateScrollPane() {
    if(camera != null) {
      PBounds pbounds = new PBounds();
      java.util.List list = camera.getLayersReference();
      PLayer player;
      for(Iterator iterator = list.iterator();iterator.hasNext();pbounds.add(player.getFullBoundsReference()))
        player = (PLayer) iterator.next();

      camera.viewToLocal(pbounds);
      PBounds pbounds1 = camera.getBoundsReference();
      pbounds.add(pbounds1);
      int i = (int) (pbounds.getWidth() + 0.5D);
      int j = (int) (pbounds.getHeight() + 0.5D);
      int k = (int) (pbounds1.getWidth() + 0.5D);
      int l = (int) (pbounds1.getHeight() + 0.5D);
      if(scrollPane.getHorizontalScrollBar().isShowing() && i <= k || !scrollPane.getHorizontalScrollBar().isShowing() && i > k || scrollPane.getVerticalScrollBar().isShowing() && j <= l || !scrollPane.getVerticalScrollBar().isShowing() && j > l)
        return true;
    }
    return false;
  }
}