/**
   * Generate the AODV animation
   *
   * @param props The properties to use for the look & feel
   * @param primitives The preconfigured primitives from the wizard
   * @return The animation as a string in AnimalScript
   */
  public String generate(AnimationPropertiesContainer props, Hashtable<String, Object> primitives) {

    controller.drawStartPage();
    controller.hideStartPage();

    controller.drawGUIGraph();

    controller.drawInfoTable(aodvGraph.getAODVNodes());
    controller.drawStatisticTable(translator.translateMessage("statTableTitle"));
    controller.drawInfoBox(translator.translateMessage("infoBox"));

    AODVNode startNode;
    AODVNode destinationNode;

    // Reset the statistics
    Statistics.sharedInstance().reset();

    for (String[] startEndNodes : routeDiscoveries) {
      startNode = aodvGraph.getNode(startEndNodes[0]);
      destinationNode = aodvGraph.getNode(startEndNodes[1]);
      if (startNode != null && destinationNode != null) {
        controller.drawNodeInfo(startNode, destinationNode);
        startAodvRouting(startNode, destinationNode);
        controller.unhighlightAll();
      }
    }

    // Draws the end page with the complexity information of AODV
    controller.drawEndPage();

    return lang.toString();
  }
  /**
   * Starts the AODV Routing Algorithm
   *
   * @param startNode Node which starts a route request to the destination node
   * @param destinationNode Node which is set as the destination for the route request.
   */
  public void startAodvRouting(AODVNode startNode, AODVNode destinationNode) {
    startNode.startRouteDiscovery(destinationNode);

    int idleNodes = 0;
    ArrayList<AODVNode> workingNodes = new ArrayList<AODVNode>(aodvGraph.getAODVNodes().size());

    // for(int i = 0; i < 4; i++) {
    while (idleNodes < aodvGraph.getAODVNodes().size()) {
      idleNodes = 0;
      workingNodes.clear();

      for (AODVNode node : aodvGraph.getAODVNodes()) {
        if (node.getCachedMessage() != null) {
          workingNodes.add(node);
        } else {
          idleNodes++;
        }
      }

      for (AODVNode node : workingNodes) {
        controller.unhighlightAll();
        node.process();
        lang.nextStep();
      }
    }
  }