public class TigerNode extends Scene {

  //Every TigerNode that is connected to this one.
  TigerNode[] connections;

  //Whether or not a tiger starts on this spot.
  //button will be blue if true, pink otherwise.
  boolean tiger_start;

  //Uses the Spot enum to determine what is in this spot.
  Spot value = Spot.EMPTY;

  //The button to press to interact with this node.
  NodeButton button;

  int x_pos;
  int y_pos;

  //side of a node's square.
  final int NODE_SIZE = 50;

  public TigerNode(int x, int y, boolean ts) {
    x_pos = x;
    y_pos = y;
    tiger_start = ts;
    button = (NodeButton) addChild( new NodeButton(x_pos, y_pos, NODE_SIZE, NODE_SIZE) );
    if (tiger_start) value = Spot.TIGER;
  }

  public void process() {
    switch (value) {
      case EMPTY:
        break;
      case TIGER:
        image(tiger_img, x_pos+ 10, y_pos-NODE_SIZE/2, NODE_SIZE*0.8, NODE_SIZE*0.8);
        break;
      case LAMB:
        image(lamb_img, x_pos+ 10, y_pos-NODE_SIZE/2, NODE_SIZE*0.8, NODE_SIZE*0.8);
        break;
    }
  }

  public void setConnections(TigerNode[] c) {
    connections = c;
    for (TigerNode n : c) {
      ((NodeWeb)((Play)getParent()).getChild(0)).addLine(x_pos, y_pos, n.x_pos, n.y_pos);
    }
  }
  
  public boolean isAdjacent(TigerNode other) {
    boolean adj = false;
    for (TigerNode t : getConnections()) {
      if (t == other) adj = true;
    }
    return adj;
  }

  public TigerNode[] getConnections() {
    return connections;
  }

  public TigerNode getConnection(int i) {
    return connections[i];
  }
  
  public Spot getValue() {
    return value;
  }
  
  public void setValue(Spot v) {
    value = v;
  }

  public int getX() {
    return x_pos;
  }

  public int getY() {
    return y_pos;
  }
  
  //Assuming this node contains a tiger and the parameter contains a lamb.
  //Sees if this node can capture the lamb node and returns the node the tiger will land.
  //returns null if the tiger cannot capture the lamb.
  public TigerNode tryCapture(TigerNode lamb) {
    TigerNode landing = null;
    if (this.getValue() == Spot.TIGER && lamb.getValue() == Spot.LAMB) {
      
      TigerNode tiger = this;
      
      int[] first_dir = tiger.getDirs(lamb);
      
      for (TigerNode n : lamb.getConnections()) {
        int[] new_dir = lamb.getDirs(n);
        if (first_dir[0] == new_dir[0] && first_dir[1] == new_dir[1] && n.getValue() == Spot.EMPTY) {
          landing = n;
        }
      }
    }
    else {
      println("canCapture has been called where it should not have been.");
      println(this.getValue());
      println(lamb.getValue());
    }
    
    return landing;
  }
  
  //helper method for canCapture that checks the relative direction of two nodes.
  public int[] getDirs(TigerNode other) {
    int x_dir;
    int y_dir;
    
    if (other.getX() > this.getX())       x_dir = 1;
    else if (other.getX() < this.getX())  x_dir = -1;
    else                                  x_dir = 0;
    
    if (other.getY() > this.getY())       y_dir = 1;
    else if (other.getY() < this.getY())  y_dir = -1;
    else                                  y_dir = 0;
    
    return new int[]{x_dir, y_dir};
  }
  
}

class NodeButton extends Button {

  TigerNode node;
  Play play;

  public NodeButton(int x_pos, int y_pos, int wid, int hei) {
    super(x_pos, y_pos, wid, hei, CENTER);
  }

  public void ready() {
    node = (TigerNode) getParent();
    play = (Play) node.getParent();

    if (node.tiger_start) {
      fill_normal = color(0, 0, 255);
      fill_hover = color(0, 0, 204);
      fill_press = color(0, 0, 127);
    } else {
      fill_normal = color(255, 0, 255);
      fill_hover = color(204, 0, 204);
      fill_press = color(127, 0, 127);
    }
  }
  
  void onRelease() {
    
    switch (play.state) {
      //START, PLACE_LAMB, MOVE_TIGER, MOVE_LAMB, LAMB_WIN, TIGER_WIN
      case PLACE_LAMB:
        if (node.getValue() == Spot.EMPTY) {
          node.setValue(Spot.LAMB);
          play.placeLamb();
          play.setState(State.PICK_TIGER);
        }
        break;
      case PICK_TIGER:
        if (node.getValue() == Spot.TIGER) {
          play.selectNode(node);
          play.setState(State.MOVE_TIGER);
        }
        break;
      case MOVE_TIGER:
        if (play.getSelectedNode().isAdjacent(node)) {
          switch (node.getValue()) {
            case EMPTY:
              node.setValue(Spot.TIGER);
              play.getSelectedNode().setValue(Spot.EMPTY);
              play.setLambTurn();
              break;
            case TIGER:
              play.setState(State.PICK_TIGER);
              break;
            case LAMB:
              if (play.getSelectedNode().tryCapture(node) != null) {
                TigerNode land = play.getSelectedNode().tryCapture(node);
                play.getSelectedNode().setValue(Spot.EMPTY);
                node.setValue(Spot.EMPTY);
                land.setValue(Spot.TIGER);
                play.setLambTurn();
              }
              break;
          }
        }
        else {
          play.setState(State.PICK_TIGER);
        }
        break;
      case PICK_LAMB:
        if (node.getValue() == Spot.LAMB) {
          play.selectNode(node);
          play.setState(State.MOVE_LAMB);
        }
        break;
      case MOVE_LAMB:
        if (node.getValue() == Spot.EMPTY) {
          if (play.getSelectedNode().isAdjacent(node)) {
            node.setValue(Spot.LAMB);
            play.getSelectedNode().setValue(Spot.EMPTY);
            play.setState(State.PICK_TIGER);
          }
        }
        else {
          play.setState(State.PICK_LAMB);
        }
        break;
      default:
        break;
    }
    
  }
  
}
