/**
 * <License>
 */
package edu.colorado.csdms.wmt.client.ui;

import java.util.List;

import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.ui.MenuBar;
import com.google.gwt.user.client.ui.MenuItem;

import edu.colorado.csdms.wmt.client.control.DataManager;
import edu.colorado.csdms.wmt.client.ui.handler.ComponentSelectionCommand;

/**
 * A menu that shows a list of components. This is the initial menu displayed in
 * a {@link ComponentCell}.
 * 
 * @author Mark Piper (mark.piper@colorado.edu)
 */
public class ComponentSelectionMenu extends MenuBar {

  private static String ALL_COMPONENTS = "__all_components";

  private DataManager data;
  private ComponentCell cell;
  private MenuItem componentItem;

  /**
   * Makes a new {@link ComponentSelectionMenu}, which shows a list of
   * components; the user chooses one to populate the {@link ComponentCell}.
   * 
   * @param data the DataManager object for the WMT session
   * @param cell the {@link ComponentCell} this menu depends on
   */
  public ComponentSelectionMenu(DataManager data, ComponentCell cell) {
    super(true); // vertical
    this.data = data;
    this.cell = cell;
    updateComponents(cell.getPortId());
  }

  /**
   * A worker for adding a new MenuItem to the {@link ComponentSelectionMenu}.
   * 
   * @param index the index into the array of available components
   */
  private void addComponentMenuItem(Integer index) {
    MenuItem item =
        new MenuItem(data.getComponent(index).getName(), true,
            new ComponentSelectionCommand(data, cell, data.getComponent(index)
                .getId()));
    item.setStyleName("wmt-ComponentSelectionMenuItem");
    this.addItem(item);
  }

  /**
   * Loads the names of the components that match the uses port of the displayed
   * component into the {@link ComponentCell} menu.
   * 
   * @param portId the id of the uses port displayed in the ComponentCell
   */
  public void updateComponents(String portId) {

    this.clearItems();

    // Display a wait message in the componentMenu.
    if (portId.matches(DataManager.DRIVER)) {
      this.addItem("Loading...", new NullCommand());
      return;
    }

    // Load all available components into the componentMenu!
    if (portId.matches(ALL_COMPONENTS)) {
      for (int i = 0; i < data.getComponents().size(); i++) {
        addComponentMenuItem(i);
      }
      return;
    }

    // Load only those components with provides ports matching the input portId.
    for (int i = 0; i < data.getComponents().size(); i++) {
      Integer nProvidesPorts = data.getComponent(i).getProvidesPorts().length();
      for (int j = 0; j < nProvidesPorts; j++) {
        if (data.getComponent(i).getProvidesPorts().get(j).getId().matches(
            portId)) {
          addComponentMenuItem(i);
        }
      }
    }
  }

  /**
   * Loads the names of all available components into the {@link ComponentCell}
   * menu.
   */
  public void updateComponents() {
    updateComponents(ALL_COMPONENTS);
  }

  /**
   * This method builds the initial list of MenuItems in the driver
   * {@link ComponentCell}. This list functions as a placeholder. Only the ids
   * of the components are displayed, and there is no command associated with
   * the MenuItems. These MenuItems are replaced with fully functional MenuItems
   * when their associated component is successfully loaded from the server.
   */
  public void initializeComponents() {
    this.clearItems();
    for (int i = 0; i < data.componentIdList.size(); i++) {
      MenuItem item =
          new MenuItem(data.componentIdList.get(i), true, new NullCommand());
      item.setStyleName("wmt-ComponentSelectionMenuItem");
      item.addStyleDependentName("missing");
      this.addItem(item);
    };
  }
  
  /**
   * Replaces a placeholder MenuItem, created by
   * {@link ComponentSelectionMenu#initializeComponents()}, with a fully
   * functional MenuItem showing the component name and having an associated
   * action.
   * 
   * @param componentId the id of the component associated with the MenuItem to
   *          replace
   */
  public void replaceMenuItem(String componentId) {
    List<MenuItem> allItems = this.getItems();
    for (int i = 0; i < allItems.size(); i++) {
      MenuItem currentItem = allItems.get(i);
      if (currentItem.getText().matches(componentId)) {
        MenuItem newItem =
            new MenuItem(data.getComponent(componentId).getName(), true,
                new ComponentSelectionCommand(data, cell, componentId));
        newItem.setStyleName("wmt-ComponentSelectionMenuItem");
        this.insertItem(newItem, i);
        this.removeItem(currentItem);
        return;
      }
    }
  }

  public MenuItem getComponentItem() {
    return componentItem;
  }

  public void setComponentItem(MenuItem componentItem) {
    this.componentItem = componentItem;
  }
  
  public class NullCommand implements Command {
    @Override
    public void execute() {
      // Do nothing
    }
  }
}

@@ -1318,62 +1318,62 @@
 ram 
-index the index i
+componentId the id of the compone
 nt
-o
  t
-he array of available components
+o add to the menu
 %0A   
@@ -1415,21 +1415,26 @@
 tem(
-Integer index
+String componentId
 ) %7B%0A
@@ -1492,21 +1492,27 @@
 mponent(
-index
+componentId
 ).getNam
@@ -1598,14 +1598,8 @@
 ent(
-index)
 %0A   
@@ -1611,16 +1611,28 @@
         
+componentId)
 .getId()
@@ -2321,36 +2321,33 @@
 0; i %3C data.
-getC
+c
 omponent
 s().size(); 
@@ -2326,35 +2326,38 @@
 %3C data.component
-s()
+IdList
 .size(); i++) %7B%0A
@@ -2352,24 +2352,82 @@
 e(); i++) %7B%0A
+        String componentId = data.componentIdList.get(i);%0A
         addC
@@ -2435,33 +2435,43 @@
 mponentMenuItem(
-i
+componentId
 );%0A      %7D%0A     
@@ -2596,28 +2596,25 @@
  %3C data.
-getC
+c
 omponent
 s().size
@@ -2605,19 +2605,22 @@
 omponent
-s()
+IdList
 .size();
@@ -2623,24 +2623,80 @@
 e(); i++) %7B%0A
+      String componentId = data.componentIdList.get(i);%0A
       Intege
@@ -2713,16 +2713,26 @@
 sPorts =
+%0A         
  data.ge
@@ -2734,33 +2734,43 @@
 ta.getComponent(
-i
+componentId
 ).getProvidesPor
@@ -2863,17 +2863,27 @@
 mponent(
-i
+componentId
 ).getPro
@@ -2909,25 +2909,16 @@
 .getId()
-.matches(
 %0A       
@@ -2922,16 +2922,25 @@
         
+.matches(
 portId))
@@ -2973,17 +2973,27 @@
 enuItem(
-i
+componentId
 );%0A     

Maintain sort order in ComponentCell menu