// IMPORT FROM PICCOLOX

package netmatch.piccolox;

import edu.umd.cs.piccolo.PCamera;
import edu.umd.cs.piccolo.PLayer;
import edu.umd.cs.piccolo.PNode;
import edu.umd.cs.piccolo.event.PDragSequenceEventHandler;
import edu.umd.cs.piccolo.event.PInputEvent;
import edu.umd.cs.piccolo.nodes.PPath;
import edu.umd.cs.piccolo.util.PBounds;
import edu.umd.cs.piccolo.util.PDimension;
import edu.umd.cs.piccolo.util.PNodeFilter;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Paint;
import java.awt.Stroke;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class PSelectionEventHandler extends PDragSequenceEventHandler {
  protected class BoundsFilter
      implements PNodeFilter {

    PBounds localBounds;
    PBounds bounds;

    public boolean accept(PNode pnode) {
      localBounds.setRect(bounds);
      pnode.globalToLocal(localBounds);
      boolean flag = pnode.intersects(localBounds);
      boolean flag1 = pnode == marquee;
      return pnode.getPickable() && flag && !flag1 && !selectableParents.contains(pnode) && !isCameraLayer(pnode);
    }

    public boolean acceptChildrenOf(PNode pnode) {
      return selectableParents.contains(pnode) || isCameraLayer(pnode);
    }

    public boolean isCameraLayer(PNode pnode) {
      label0:
      {
        if(!(pnode instanceof PLayer))
          break label0;
        Iterator iterator = selectableParents.iterator();
        PNode pnode1;
        do {
          if(!iterator.hasNext())
            break label0;
          pnode1 = (PNode) iterator.next();
        }
        while(!(pnode1 instanceof PCamera) || ((PCamera) pnode1).indexOfLayer((PLayer) pnode) == -1);
        return true;
      }
      return false;
    }

    protected BoundsFilter(PBounds pbounds) {
      localBounds = new PBounds();
      bounds = pbounds;
    }
  }


  public static final String SELECTION_CHANGED_NOTIFICATION = "SELECTION_CHANGED_NOTIFICATION";
  static final int DASH_WIDTH = 5;
  static final int NUM_STROKES = 10;
  private HashMap selection;
  private java.util.List selectableParents;
  private PPath marquee;
  private PNode marqueeParent;
  private Point2D presspt;
  private Point2D canvasPressPt;
  private float strokeNum;
  private Stroke strokes[];
  private HashMap allItems;
  private ArrayList unselectList;
  private HashMap marqueeMap;
  private PNode pressNode;
  private boolean deleteKeyActive;
  private Paint marqueePaint;
  private float marqueePaintTransparency;

  public PSelectionEventHandler(PNode pnode, PNode pnode1) {
    selection = null;
    selectableParents = null;
    marquee = null;
    marqueeParent = null;
    presspt = null;
    canvasPressPt = null;
    strokeNum = 0.0F;
    strokes = null;
    allItems = null;
    unselectList = null;
    marqueeMap = null;
    pressNode = null;
    deleteKeyActive = true;
    marqueePaintTransparency = 1.0F;
    marqueeParent = pnode;
    selectableParents = new ArrayList();
    selectableParents.add(pnode1);
    init();
  }

  public PSelectionEventHandler(PNode pnode, java.util.List list) {
    selection = null;
    selectableParents = null;
    marquee = null;
    marqueeParent = null;
    presspt = null;
    canvasPressPt = null;
    strokeNum = 0.0F;
    strokes = null;
    allItems = null;
    unselectList = null;
    marqueeMap = null;
    pressNode = null;
    deleteKeyActive = true;
    marqueePaintTransparency = 1.0F;
    marqueeParent = pnode;
    selectableParents = list;
    init();
  }

  protected void init() {
    float af[] = {
        5F,5F
    };
    strokes = new Stroke[10];
    for(int i = 0;i < 10;i++)
      strokes[i] = new BasicStroke(1.0F, 0, 0, 1.0F, af, i);

    selection = new HashMap();
    allItems = new HashMap();
    unselectList = new ArrayList();
    marqueeMap = new HashMap();
  }

  public void select(Collection collection) {
    boolean flag = false;
    for(Iterator iterator = collection.iterator();iterator.hasNext();) {
      PNode pnode = (PNode) iterator.next();
      flag |= internalSelect(pnode);
    }

    if(flag)
      postSelectionChanged();
  }

  public void select(Map map) {
    select(((Collection) (map.keySet())));
  }

  private boolean internalSelect(PNode pnode) {
    if(isSelected(pnode)) {
      return false;
    }
    else {
      selection.put(pnode, Boolean.TRUE);
      decorateSelectedNode(pnode);
      return true;
    }
  }

  private void postSelectionChanged() {
    PNotificationCenter.defaultCenter().postNotification("SELECTION_CHANGED_NOTIFICATION", this);
  }

  public void select(PNode pnode) {
    if(internalSelect(pnode))
      postSelectionChanged();
  }

  public void decorateSelectedNode(PNode pnode) {
    PBoundsHandle.addBoundsHandlesTo(pnode);
  }

  public void unselect(Collection collection) {
    boolean flag = false;
    for(Iterator iterator = collection.iterator();iterator.hasNext();) {
      PNode pnode = (PNode) iterator.next();
      flag |= internalUnselect(pnode);
    }

    if(flag)
      postSelectionChanged();
  }

  private boolean internalUnselect(PNode pnode) {
    if(!isSelected(pnode)) {
      return false;
    }
    else {
      undecorateSelectedNode(pnode);
      selection.remove(pnode);
      return true;
    }
  }

  public void unselect(PNode pnode) {
    if(internalUnselect(pnode))
      postSelectionChanged();
  }

  public void undecorateSelectedNode(PNode pnode) {
    PBoundsHandle.removeBoundsHandlesFrom(pnode);
  }

  public void unselectAll() {
    ArrayList arraylist = new ArrayList(selection.keySet());
    unselect(arraylist);
  }

  public boolean isSelected(PNode pnode) {
    return pnode != null && selection.containsKey(pnode);
  }

  public Collection getSelection() {
    ArrayList arraylist = new ArrayList(selection.keySet());
    return arraylist;
  }

  public Collection getSelectionReference() {
    return Collections.unmodifiableCollection(selection.keySet());
  }

  protected boolean isSelectable(PNode pnode) {
    boolean flag = false;
    Iterator iterator = selectableParents.iterator();
    label0:
    do {
      if(iterator.hasNext()) {
        PNode pnode1 = (PNode) iterator.next();
        if(pnode1.getChildrenReference().contains(pnode)) {
          flag = true;
        }
        else {
          if(!(pnode1 instanceof PCamera))
            continue;
          int i = 0;
          do {
            if(i >= ((PCamera) pnode1).getLayerCount())
              continue label0;
            PLayer player = ((PCamera) pnode1).getLayer(i);
            if(player.getChildrenReference().contains(pnode)) {
              flag = true;
              continue label0;
            }
            i++;
          }
          while(true);
        }
      }
      return flag;
    }
    while(true);
  }

  public void addSelectableParent(PNode pnode) {
    selectableParents.add(pnode);
  }

  public void removeSelectableParent(PNode pnode) {
    selectableParents.remove(pnode);
  }

  public void setSelectableParent(PNode pnode) {
    selectableParents.clear();
    selectableParents.add(pnode);
  }

  public void setSelectableParents(Collection collection) {
    selectableParents.clear();
    selectableParents.addAll(collection);
  }

  public Collection getSelectableParents() {
    return new ArrayList(selectableParents);
  }

  protected void startDrag(PInputEvent pinputevent) {
    super.startDrag(pinputevent);
    initializeSelection(pinputevent);
    if(isMarqueeSelection(pinputevent)) {
      initializeMarquee(pinputevent);
      if(!isOptionSelection(pinputevent))
        startMarqueeSelection(pinputevent);
      else
        startOptionMarqueeSelection(pinputevent);
    }
    else if(!isOptionSelection(pinputevent))
      startStandardSelection(pinputevent);
    else
      startStandardOptionSelection(pinputevent);
  }

  protected void drag(PInputEvent pinputevent) {
    super.drag(pinputevent);
    if(isMarqueeSelection(pinputevent)) {
      updateMarquee(pinputevent);
      if(!isOptionSelection(pinputevent))
        computeMarqueeSelection(pinputevent);
      else
        computeOptionMarqueeSelection(pinputevent);
    }
    else {
      dragStandardSelection(pinputevent);
    }
  }

  protected void endDrag(PInputEvent pinputevent) {
    super.endDrag(pinputevent);
    if(isMarqueeSelection(pinputevent))
      endMarqueeSelection(pinputevent);
    else
      endStandardSelection(pinputevent);
  }

  public boolean isOptionSelection(PInputEvent pinputevent) {
    return pinputevent.isShiftDown();
  }

  protected boolean isMarqueeSelection(PInputEvent pinputevent) {
    return pressNode == null;
  }

  protected void initializeSelection(PInputEvent pinputevent) {
    canvasPressPt = pinputevent.getCanvasPosition();
    presspt = pinputevent.getPosition();
    pressNode = pinputevent.getPath().getPickedNode();
    if(pressNode instanceof PCamera)
      pressNode = null;
  }

  protected void initializeMarquee(PInputEvent pinputevent) {
    marquee = PPath.createRectangle((float) presspt.getX(), (float) presspt.getY(), 0.0F, 0.0F);
    marquee.setPaint(marqueePaint);
    marquee.setTransparency(marqueePaintTransparency);
    marquee.setStrokePaint(Color.black);
    marquee.setStroke(strokes[0]);
    marqueeParent.addChild(marquee);
    marqueeMap.clear();
  }

  protected void startOptionMarqueeSelection(PInputEvent pinputevent) {
  }

  protected void startMarqueeSelection(PInputEvent pinputevent) {
    unselectAll();
  }

  protected void startStandardSelection(PInputEvent pinputevent) {
    if(!isSelected(pressNode)) {
      unselectAll();
      if(isSelectable(pressNode))
        select(pressNode);
    }
  }

  protected void startStandardOptionSelection(PInputEvent pinputevent) {
    if(isSelectable(pressNode))
      if(isSelected(pressNode))
        unselect(pressNode);
      else
        select(pressNode);
  }

  protected void updateMarquee(PInputEvent pinputevent) {
    PBounds pbounds = new PBounds();
    if(marqueeParent instanceof PCamera) {
      pbounds.add(canvasPressPt);
      pbounds.add(pinputevent.getCanvasPosition());
    }
    else {
      pbounds.add(presspt);
      pbounds.add(pinputevent.getPosition());
    }
    marquee.setPathToRectangle((float) pbounds.x, (float) pbounds.y, (float) pbounds.width, (float) pbounds.height);
    pbounds.reset();
    pbounds.add(presspt);
    pbounds.add(pinputevent.getPosition());
    allItems.clear();
    PNodeFilter pnodefilter = createNodeFilter(pbounds);
    for(Iterator iterator = selectableParents.iterator();iterator.hasNext();) {
      PNode pnode = (PNode) iterator.next();
      Object obj;
      if(pnode instanceof PCamera) {
        obj = new ArrayList();
        for(int i = 0;i < ((PCamera) pnode).getLayerCount();i++)
          ((PCamera) pnode).getLayer(i).getAllNodes(pnodefilter, ((Collection) (obj)));

      }
      else {
        obj = pnode.getAllNodes(pnodefilter, null);
      }
      Iterator iterator1 = ((Collection) (obj)).iterator();
      while(iterator1.hasNext())
        allItems.put(iterator1.next(), Boolean.TRUE);
    }

  }

  protected void computeMarqueeSelection(PInputEvent pinputevent) {
    unselectList.clear();
    Iterator iterator = selection.keySet().iterator();
    do {
      if(!iterator.hasNext())
        break;
      PNode pnode = (PNode) iterator.next();
      if(!allItems.containsKey(pnode))
        unselectList.add(pnode);
    }
    while(true);
    unselect(unselectList);
    iterator = allItems.keySet().iterator();
    do {
      if(!iterator.hasNext())
        break;
      PNode pnode1 = (PNode) iterator.next();
      if(!selection.containsKey(pnode1) && !marqueeMap.containsKey(pnode1) && isSelectable(pnode1))
        marqueeMap.put(pnode1, Boolean.TRUE);
      else if(!isSelectable(pnode1))
        allItems.remove(pnode1);
    }
    while(true);
    select(allItems);
  }

  protected void computeOptionMarqueeSelection(PInputEvent pinputevent) {
    unselectList.clear();
    Iterator iterator = selection.keySet().iterator();
    do {
      if(!iterator.hasNext())
        break;
      PNode pnode = (PNode) iterator.next();
      if(!allItems.containsKey(pnode) && marqueeMap.containsKey(pnode)) {
        marqueeMap.remove(pnode);
        unselectList.add(pnode);
      }
    }
    while(true);
    unselect(unselectList);
    iterator = allItems.keySet().iterator();
    do {
      if(!iterator.hasNext())
        break;
      PNode pnode1 = (PNode) iterator.next();
      if(!selection.containsKey(pnode1) && !marqueeMap.containsKey(pnode1) && isSelectable(pnode1))
        marqueeMap.put(pnode1, Boolean.TRUE);
      else if(!isSelectable(pnode1))
        allItems.remove(pnode1);
    }
    while(true);
    select(allItems);
  }

  protected PNodeFilter createNodeFilter(PBounds pbounds) {
    return new BoundsFilter(pbounds);
  }

  protected PBounds getMarqueeBounds() {
    if(marquee != null)
      return marquee.getBounds();
    else
      return new PBounds();
  }

  protected void dragStandardSelection(PInputEvent pinputevent) {
    PDimension pdimension = pinputevent.getCanvasDelta();
    pinputevent.getTopCamera().localToView(pdimension);
    PDimension pdimension1 = new PDimension();
    PNode pnode;
    for(Iterator iterator = selection.keySet().iterator();iterator.hasNext();pnode.offset(pdimension.getWidth(), pdimension.getHeight()))
    {
      pnode = (PNode) iterator.next();
      pdimension1.setSize(pdimension);
      pnode.getParent().globalToLocal(pdimension);
    }

  }

  protected void endMarqueeSelection(PInputEvent pinputevent) {
    marquee.removeFromParent();
    marquee = null;
  }

  protected void endStandardSelection(PInputEvent pinputevent) {
    pressNode = null;
  }

  protected void dragActivityStep(PInputEvent pinputevent) {
    if(marquee != null) {
      float f = strokeNum;
      strokeNum = (strokeNum + 0.5F) % 10F;
      if((int) strokeNum != (int) f)
        marquee.setStroke(strokes[(int) strokeNum]);
    }
  }

  public void keyPressed(PInputEvent pinputevent) {
    switch(pinputevent.getKeyCode()) {
      default:
        break;

      case 127:// '\177'
        if(deleteKeyActive) {
          PNode pnode;
          for(Iterator iterator = selection.keySet().iterator();iterator.hasNext();pnode.removeFromParent())
            pnode = (PNode) iterator.next();

          selection.clear();
        }
        break;
    }
  }

  public boolean getSupportDeleteKey() {
    return deleteKeyActive;
  }

  public boolean isDeleteKeyActive() {
    return deleteKeyActive;
  }

  public void setDeleteKeyActive(boolean flag) {
    deleteKeyActive = flag;
  }

  public Paint getMarqueePaint() {
    return marqueePaint;
  }

  public void setMarqueePaint(Paint paint) {
    marqueePaint = paint;
  }

  public float getMarqueePaintTransparency() {
    return marqueePaintTransparency;
  }

  public void setMarqueePaintTransparency(float f) {
    marqueePaintTransparency = f;
  }


}