/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.log4j.chainsaw.receivers;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import java.io.File;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JToolBar;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.ExpandVetoException;
import javax.swing.tree.TreePath;

import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.chainsaw.PopupListener;
import org.apache.log4j.chainsaw.SmallButton;
import org.apache.log4j.chainsaw.prefs.SettingsManager;
import org.apache.log4j.chainsaw.prefs.SettingsListener;
import org.apache.log4j.chainsaw.prefs.SaveSettingsEvent;
import org.apache.log4j.chainsaw.prefs.LoadSettingsEvent;
import org.apache.log4j.chainsaw.help.HelpManager;
import org.apache.log4j.chainsaw.helper.SwingHelper;
import org.apache.log4j.chainsaw.icons.ChainsawIcons;
import org.apache.log4j.chainsaw.icons.LevelIconFactory;
import org.apache.log4j.chainsaw.icons.LineIconFactory;
import org.apache.log4j.chainsaw.messages.MessageCenter;
import org.apache.log4j.net.SocketNodeEventListener;
import org.apache.log4j.net.SocketReceiver;
import org.apache.log4j.plugins.Pauseable;
import org.apache.log4j.plugins.Plugin;
import org.apache.log4j.plugins.PluginEvent;
import org.apache.log4j.plugins.PluginListener;
import org.apache.log4j.plugins.PluginRegistry;
import org.apache.log4j.plugins.Receiver;
import org.apache.log4j.spi.LoggerRepository;
import org.apache.log4j.spi.LoggerRepositoryEx;


/**
 * This panel is used to manage all the Receivers configured within Log4j
 *
 *
 * @author Paul Smith &lt;psmith@apache.org&gt;
 * @author Scott Deboy &lt;sdeboy@apache.org&gt;
 */
public class ReceiversPanel extends JPanel implements SettingsListener {
  final Action newReceiverButtonAction;
  final Action pauseReceiverButtonAction;
  final Action playReceiverButtonAction;
  final Action shutdownReceiverButtonAction;
  final Action saveReceiversButtonAction;
  final Action restartReceiverButtonAction;
  private final Action showReceiverHelpAction;
  private final Action startAllAction;
  private final JPopupMenu popupMenu = new ReceiverPopupMenu();
  private final JTree receiversTree = new JTree();
  private final NewReceiverPopupMenu newReceiverPopup =
    new NewReceiverPopupMenu();
  private final ReceiverToolbar buttonPanel;
  private final JSplitPane splitter = new JSplitPane();
  private final PluginPropertyEditorPanel pluginEditorPanel =
    new PluginPropertyEditorPanel();
  private final Logger logger = LogManager.getLogger(ReceiversPanel.class);
  
  private final PluginRegistry pluginRegistry;
  

  public ReceiversPanel() {
    super(new BorderLayout());
    LoggerRepository repo = LogManager.getLoggerRepository();
    final ReceiversTreeModel model = new ReceiversTreeModel();
    if (repo instanceof LoggerRepositoryEx) {
       pluginRegistry = ((LoggerRepositoryEx) repo).getPluginRegistry();
       pluginRegistry.addPluginListener(model);

       //iterate over visual receivers and call setcontainer
       Collection c = pluginRegistry.getPlugins(VisualReceiver.class);
        for (Object aC : c) {
            ((VisualReceiver) aC).setContainer(this);
        }
       
       pluginRegistry.addPluginListener(new PluginListener() {
		public void pluginStarted(PluginEvent e) {
			//if we get a plugin started callback, set the container
			if (e.getPlugin() instanceof VisualReceiver) {
				((VisualReceiver)e.getPlugin()).setContainer(ReceiversPanel.this);
			}
		}

		public void pluginStopped(PluginEvent e) {
		}
       });
    } else {
       pluginRegistry = null;
    }
    
    receiversTree.setModel(model);

    receiversTree.setExpandsSelectedPaths(true);
    model.addTreeModelListener(
      new TreeModelListener() {
        public void treeNodesChanged(TreeModelEvent e) {
          expandRoot();
        }

        public void treeNodesInserted(TreeModelEvent e) {
          expandRoot();
        }

        public void treeNodesRemoved(TreeModelEvent e) {
          expandRoot();
        }

        public void treeStructureChanged(TreeModelEvent e) {
          expandRoot();
        }

        private void expandRoot() {
          receiversTree.expandPath(
            new TreePath(model.getPathToRoot(model.RootNode)));
        }
      });
    receiversTree.expandPath(
      new TreePath(model.getPathToRoot(model.RootNode)));

    receiversTree.addTreeWillExpandListener(
      new TreeWillExpandListener() {
        public void treeWillCollapse(TreeExpansionEvent event)
          throws ExpandVetoException {
          if (event.getPath().getLastPathComponent() == model.RootNode) {
            throw new ExpandVetoException(event);
          }
        }

        public void treeWillExpand(TreeExpansionEvent event) {
        }
      });

    receiversTree.addTreeSelectionListener(
            e -> {
              TreePath path = e.getNewLeadSelectionPath();

              if (path != null) {
                DefaultMutableTreeNode node =
                  (DefaultMutableTreeNode) path.getLastPathComponent();

                if (
                  (node != null) && (node.getUserObject() != null)
                    && (node.getUserObject() instanceof Plugin)) {
                  Plugin p = (Plugin) node.getUserObject();
                  logger.debug("plugin=" + p);
                  pluginEditorPanel.setPlugin(p);
                } else {
                  pluginEditorPanel.setPlugin(null);
                }
              }
            });

    receiversTree.setToolTipText("Allows you to manage Log4j Receivers");
    newReceiverButtonAction =
      new AbstractAction() {
          public void actionPerformed(ActionEvent e) {
            newReceiverPopup.show(
              buttonPanel.newReceiverButton, 0,
              buttonPanel.newReceiverButton.getHeight());
          }
        };
    newReceiverButtonAction.putValue(
      Action.SMALL_ICON, new ImageIcon(ChainsawIcons.ICON_NEW_RECEIVER));
    newReceiverButtonAction.putValue(
      Action.SHORT_DESCRIPTION, "Creates and configures a new Receiver");
    newReceiverButtonAction.putValue(Action.NAME, "New Receiver");
    newReceiverButtonAction.putValue(
      Action.MNEMONIC_KEY, KeyEvent.VK_N);

    newReceiverButtonAction.setEnabled(true);

    playReceiverButtonAction =
      new AbstractAction() {
          public void actionPerformed(ActionEvent e) {
            playCurrentlySelectedReceiver();
          }
        };

    playReceiverButtonAction.putValue(
      Action.SHORT_DESCRIPTION, "Resumes the selected Node");
    playReceiverButtonAction.putValue(Action.NAME, "Resume");
    playReceiverButtonAction.putValue(
      Action.SMALL_ICON, new ImageIcon(ChainsawIcons.ICON_RESUME_RECEIVER));
    playReceiverButtonAction.setEnabled(false);
    playReceiverButtonAction.putValue(
      Action.MNEMONIC_KEY, KeyEvent.VK_R);

    pauseReceiverButtonAction =
      new AbstractAction() {
          public void actionPerformed(ActionEvent e) {
            pauseCurrentlySelectedReceiver();
          }
        };

    pauseReceiverButtonAction.putValue(
      Action.SHORT_DESCRIPTION,
      "Pause the selected Receiver.  All events received will be discarded.");
    pauseReceiverButtonAction.putValue(Action.NAME, "Pause");

    pauseReceiverButtonAction.putValue(
      Action.MNEMONIC_KEY, KeyEvent.VK_P);

    pauseReceiverButtonAction.putValue(
      Action.SMALL_ICON, new ImageIcon(ChainsawIcons.PAUSE));
    pauseReceiverButtonAction.setEnabled(false);

    shutdownReceiverButtonAction =
      new AbstractAction() {
          public void actionPerformed(ActionEvent e) {
            shutdownCurrentlySelectedReceiver();
          }
        };

    shutdownReceiverButtonAction.putValue(
      Action.SHORT_DESCRIPTION,
      "Shuts down the selected Receiver, and removes it from the Plugin registry");
    shutdownReceiverButtonAction.putValue(Action.NAME, "Shutdown");

    shutdownReceiverButtonAction.putValue(
      Action.SMALL_ICON, new ImageIcon(ChainsawIcons.ICON_STOP_RECEIVER));
    shutdownReceiverButtonAction.putValue(
      Action.MNEMONIC_KEY, KeyEvent.VK_S);

    shutdownReceiverButtonAction.setEnabled(false);

    saveReceiversButtonAction =
      new AbstractAction() {
          public void actionPerformed(ActionEvent e) {
            saveReceivers();
          }
        };

    saveReceiversButtonAction.putValue(
      Action.SHORT_DESCRIPTION,
      "Save the current receiver configuration");
    saveReceiversButtonAction.putValue(Action.NAME, "Save receivers");

    saveReceiversButtonAction.putValue(
      Action.SMALL_ICON, new ImageIcon(ChainsawIcons.FILE_SAVE_AS));
    saveReceiversButtonAction.putValue(
      Action.MNEMONIC_KEY, KeyEvent.VK_V);


    restartReceiverButtonAction =
        new AbstractAction() {
            public void actionPerformed(ActionEvent e) {
              Receiver selectedReceiver = getCurrentlySelectedReceiver();
              if(selectedReceiver == null){
              	return;
              }
              selectedReceiver.shutdown();
              selectedReceiver.activateOptions();
              //allow the visual receiver to get a container on restart
              if (selectedReceiver instanceof VisualReceiver) {
                  ((VisualReceiver)selectedReceiver).setContainer(ReceiversPanel.this);
              }
            }
          };

      restartReceiverButtonAction.putValue(
        Action.SHORT_DESCRIPTION,
        "Restarts the selected Receiver");
      restartReceiverButtonAction.putValue(Action.NAME, "Restart");

      restartReceiverButtonAction.putValue(
        Action.SMALL_ICON, new ImageIcon(ChainsawIcons.ICON_RESTART));
      restartReceiverButtonAction.putValue(
        Action.MNEMONIC_KEY, KeyEvent.VK_R);

      restartReceiverButtonAction.setEnabled(false);

    showReceiverHelpAction =
      new AbstractAction("Help") {
          public void actionPerformed(ActionEvent e) {
            Receiver receiver = getCurrentlySelectedReceiver();

            if (receiver != null) {
              HelpManager.getInstance().showHelpForClass(receiver.getClass());
            }
          }
        };

    showReceiverHelpAction.putValue(
      Action.SMALL_ICON, new ImageIcon(ChainsawIcons.HELP));
    showReceiverHelpAction.putValue(
      Action.SHORT_DESCRIPTION, "Displays the JavaDoc page for this Plugin");

    startAllAction =
      new AbstractAction(
        "(Re)start All Receivers", new ImageIcon(ChainsawIcons.ICON_RESTART_ALL)) {
          public void actionPerformed(ActionEvent e) {
            if (
              JOptionPane.showConfirmDialog(
                  null,
                  "This will cause any active Receiver to stop, and disconnect.  Is this ok?",
                  "Confirm", JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) {
              new Thread(
                      () -> {
                        Collection allReceivers =
                            pluginRegistry.getPlugins(Receiver.class);

                          for (Object allReceiver : allReceivers) {
                              Receiver item = (Receiver) allReceiver;
                              item.shutdown();
                              item.activateOptions();
                          }

                        updateReceiverTreeInDispatchThread();
                        MessageCenter.getInstance().getLogger().info(
                          "All Receivers have been (re)started");
                      }).start();
            }
          }
        };

    startAllAction.putValue(
      Action.SHORT_DESCRIPTION,
      "Ensures that any Receiver that isn't active, is started, and any started action is stopped, and then restarted");

    receiversTree.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    receiversTree.setCellRenderer(new ReceiverTreeCellRenderer());
    receiversTree.setRowHeight(19);

    buttonPanel = new ReceiverToolbar();
    receiversTree.addTreeSelectionListener(buttonPanel);

    PopupListener popupListener = new PopupListener(popupMenu);
    receiversTree.addMouseListener(popupListener);
    this.addMouseListener(popupListener);

    JComponent component = receiversTree;
    JScrollPane pane = new JScrollPane(component);

    splitter.setOrientation(JSplitPane.VERTICAL_SPLIT);

    splitter.setTopComponent(pane);
    splitter.setBottomComponent(pluginEditorPanel);

    splitter.setResizeWeight(0.7);
    add(buttonPanel, BorderLayout.NORTH);
    add(splitter, BorderLayout.CENTER);

    /**
     * This Tree likes to be notified when Socket's are accepted so
     * we listen for them and update the Tree.
     */
    SocketNodeEventListener listener =
      new SocketNodeEventListener() {
        public void socketOpened(String remoteInfo) {
          updateReceiverTreeInDispatchThread();
        }

        public void socketClosedEvent(Exception e) {
          updateReceiverTreeInDispatchThread();
        }
      };

    /**
     * add this listener to all SocketReceivers
     */
    if (pluginRegistry != null) {
    	List socketReceivers =
      		pluginRegistry.getPlugins(SocketReceiver.class);

        for (Object socketReceiver : socketReceivers) {
            SocketReceiver element = (SocketReceiver) socketReceiver;
            element.addSocketNodeEventListener(listener);
        }
     }
  }

  private void saveReceivers() {
    File saveConfigFile = SwingHelper.promptForFile(this, null, "Save receiver configuration XML file", false);
    if (saveConfigFile != null) {
      ReceiversHelper.getInstance().saveReceiverConfiguration(saveConfigFile);
    }
  }

  protected ReceiversTreeModel getReceiverTreeModel() {
    return ((ReceiversTreeModel) receiversTree.getModel());
  }

  /**
   *
   */
  protected void updateCurrentlySelectedNodeInDispatchThread() {
    SwingUtilities.invokeLater(
            () -> {
              DefaultMutableTreeNode node =
                (DefaultMutableTreeNode) receiversTree
                .getLastSelectedPathComponent();

              if (node == null) {
                return;
              }

              getReceiverTreeModel().nodeChanged(node);
              updateActions();
            });
  }

  /**
   * Returns the currently selected Receiver, or null if there is no
   * selected Receiver (this could be because a) nothing at all is selected
   * or b) a non Receiver type node is selected
   *
   * @return Receiver or null
   */
  private Receiver getCurrentlySelectedReceiver() {
    DefaultMutableTreeNode node =
      (DefaultMutableTreeNode) receiversTree.getLastSelectedPathComponent();

    if (node == null) {
      return null;
    }

    Object userObject = node.getUserObject();

    if (userObject instanceof Receiver) {
      return (Receiver) userObject;
    }

    return null;
  }

  private Receiver[] getSelectedReceivers() {
    TreePath[] paths = receiversTree.getSelectionPaths();
    Collection receivers = new ArrayList();

      for (TreePath path : paths) {
          DefaultMutableTreeNode node =
                  (DefaultMutableTreeNode) path.getLastPathComponent();

          if ((node != null) && node.getUserObject() instanceof Receiver) {
              receivers.add(node.getUserObject());
          }
      }

    return (Receiver[]) receivers.toArray(new Receiver[0]);
  }

  /**
   * Returns the currently seleted node's User Object, or null
   * if there is no selected node, or if the currently selected node has
   * not user Object
   * @return Object representing currently seleted Node's User Object
   */
  private Object getCurrentlySelectedUserObject() {
    DefaultMutableTreeNode node =
      (DefaultMutableTreeNode) receiversTree.getLastSelectedPathComponent();

    if (node == null) {
      return null;
    }

    return node.getUserObject();
  }

  /**
   * Takes the currently selected Receiver and pauess it, effectively
   * discarding any received event BEFORE it is even posted to the logger
   * repository.
   *
   * The user is NOT asked to confirm this operation
   *
   */
  private void pauseCurrentlySelectedReceiver() {
    new Thread(
            () -> {
              Object obj = getCurrentlySelectedUserObject();

              if ((obj != null) && obj instanceof Pauseable) {
                ((Pauseable) obj).setPaused(true);
                updateCurrentlySelectedNodeInDispatchThread();
              }
            }).start();
  }

  /**
   * Ensures that the currently selected receiver active property is set to
   * true
   *
   */
  private void playCurrentlySelectedReceiver() {
    new Thread(
            () -> {
              Object obj = getCurrentlySelectedUserObject();

              if ((obj != null) && obj instanceof Pauseable) {
                ((Pauseable) obj).setPaused(false);

                updateCurrentlySelectedNodeInDispatchThread();
              }
            }).start();
  }

  /**
   * Takes the currently selected Receiver and stops it, which effectively
   * removes it from the PluginRegistry.
   *
   * The user is asked to confirm this operation
   *
   */
  private void shutdownCurrentlySelectedReceiver() {
    if (
      JOptionPane.showConfirmDialog(
          null,
          "Are you sure you wish to shutdown this receiver?\n\nThis will disconnect any network resources, and remove it from the PluginRegistry.",
          "Confirm stop of Receiver", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
      new Thread(
              () -> {
                Receiver[] receivers = getSelectedReceivers();

                if (receivers != null) {
                    for (Receiver receiver : receivers) {
                        pluginRegistry.stopPlugin(receiver.getName());
                    }
                }
              }).start();
    }
  }

  /**
   * Sets the state of actions depending on certain conditions (i.e what is
   * currently selected etc.)
   */
  private void updateActions() {
    Object object = getCurrentlySelectedUserObject();

    if ((object != null) && object instanceof Pauseable) {
      Pauseable pauseable = (Pauseable) object;

      if (!pauseable.isPaused()) {
        pauseReceiverButtonAction.setEnabled(true);
        playReceiverButtonAction.setEnabled(false);
      } else {
        pauseReceiverButtonAction.setEnabled(false);
        playReceiverButtonAction.setEnabled(true);
      }
    } else {
      pauseReceiverButtonAction.setEnabled(false);
      playReceiverButtonAction.setEnabled(false);
    }

    if (object instanceof Receiver) {
      newReceiverButtonAction.setEnabled(true);
      shutdownReceiverButtonAction.setEnabled(true);
      restartReceiverButtonAction.setEnabled(true);
    } else {
      shutdownReceiverButtonAction.setEnabled(false);
      restartReceiverButtonAction.setEnabled(false);
    }
  }

  /**
   * Ensures that the Receiver tree is updated with the latest information
   * and that this operation occurs in the Swing Event Dispatch thread.
   *
   */
  public void updateReceiverTreeInDispatchThread() {
    logger.debug(
      "updateReceiverTreeInDispatchThread, should not be needed now");

    //    if (SwingUtilities.isEventDispatchThread()) {
    //      updateReceiverTree.run();
    //    } else {
    //      SwingUtilities.invokeLater(updateReceiverTree);
    //    }
  }

  /* (non-Javadoc)
   * @see java.awt.Component#setVisible(boolean)
   */
  public void setVisible(boolean aFlag) {
    boolean oldValue = isVisible();
    super.setVisible(aFlag);
    firePropertyChange("visible", oldValue, isVisible());
  }

  public void loadSettings(LoadSettingsEvent event){}

   /**
    * Saves all the receivers which are active at shut down as a configuration
    * file which can be loaded when Chainsaw will be restarted.
    */

  public void saveSettings(SaveSettingsEvent event){
     File file = new File(SettingsManager.getInstance().getSettingsDirectory(), "receiver-config.xml");
     ReceiversHelper.getInstance().saveReceiverConfiguration(file);
  }

  /**
   * A popup menu that allows the user to choose which
   * style of Receiver to create, which spawns a relevant Dialog
   * to enter the information and create the Receiver
   *
   * @author Paul Smith &lt;psmith@apache.org&gt;
   *
   */
  class NewReceiverPopupMenu extends JPopupMenu {
    NewReceiverPopupMenu() {
      try {
        final List receiverList =
          ReceiversHelper.getInstance().getKnownReceiverClasses();
        String separatorCheck = null;

          for (Object aReceiverList : receiverList) {
              final Class toCreate = (Class) aReceiverList;
              Package thePackage = toCreate.getPackage();
              final String name =
                      toCreate.getName().substring(thePackage.getName().length() + 1);

              if (separatorCheck == null) {
                  separatorCheck = name.substring(0, 1);
              } else {
                  String current = name.substring(0, 1);

                  if (!current.equals(separatorCheck)) {
                      addSeparator();
                      separatorCheck = current;
                  }
              }

              add(
                      new AbstractAction("New " + name + "...") {
                          public void actionPerformed(ActionEvent e) {
                              Container container = SwingUtilities.getAncestorOfClass(JFrame.class, ReceiversPanel.this);
                              final JDialog dialog = new JDialog((JFrame) container, "New " + toCreate.getName() + "...", true);

                              try {
                                  final NewReceiverDialogPanel panel =
                                          NewReceiverDialogPanel.create(toCreate);
                                  dialog.getContentPane().add(panel);
                                  dialog.pack();
                                  SwingHelper.centerOnScreen(dialog);

                                  /**
                                   * Make the default button the ok button
                                   */
                                  dialog.getRootPane().setDefaultButton(panel.getOkPanel().getOkButton());

                                  /**
                                   * Use the standard Cancel metaphor
                                   */
                                  SwingHelper.configureCancelForDialog(dialog, panel.getOkPanel().getCancelButton());


                                  panel.getOkPanel().getOkButton().addActionListener(
                                          e2 -> {
                                              Plugin plugin = panel.getPlugin();
                                              if (plugin.getName() != null && !plugin.getName().trim().equals("")) {
                                                  dialog.dispose();
                                                  pluginRegistry.addPlugin(plugin);
                                                  plugin.activateOptions();
                                                  MessageCenter.getInstance().addMessage("Plugin '" + plugin.getName() + "' started");
                                              } else {
                                                  MessageCenter.getInstance().getLogger().error("Name required to create receiver");
                                              }
                                          });
                                  dialog.setVisible(true);
                              } catch (Exception e1) {
                                  e1.printStackTrace();
                                  MessageCenter.getInstance().getLogger().error(
                                          "Failed to create the new Receiver dialog", e1);
                              }
                          }
                      });
          }
      } catch (Exception e) {
        e.printStackTrace();
        throw new RuntimeException(e.getMessage());
      }
    }
  }

  /**
   * A popup menu class for when the user uses the popup trigger action
   * on a node in the Receiver tree.
   *
   * @author Paul Smith &lt;psmith@apache.org&gt;
   *
   */
  class ReceiverPopupMenu extends JPopupMenu {
    ReceiverPopupMenu() {
    }

    /* (non-Javadoc)
     * @see javax.swing.JPopupMenu#show(java.awt.Component, int, int)
     */
    public void show(Component invoker, int x, int y) {
      DefaultMutableTreeNode node =
        (DefaultMutableTreeNode) receiversTree.getLastSelectedPathComponent();

      if (node == null) {
        return;
      }

      Object userObject = node.getUserObject();
      removeAll();

      if (userObject == getRootOfTree().getUserObject()) {
        buildForReceiversRoot();
      } else if (getCurrentlySelectedReceiver() != null) {
        buildForReceiverNode();
      } else {
        return;
      }

      this.invalidate();
      this.validate();

      super.show(invoker, x, y);
    }

    /**
     *
     */
    private DefaultMutableTreeNode getRootOfTree() {
      return (DefaultMutableTreeNode) receiversTree.getModel().getRoot();
    }

    /**
     * Builds the popup menu with relevant items for a selected
     * Receiver node in the Tree.
     */
    private void buildForReceiverNode() {

      add(playReceiverButtonAction);
      add(pauseReceiverButtonAction);
      add(restartReceiverButtonAction);
      add(shutdownReceiverButtonAction);
      add(saveReceiversButtonAction);

      addSeparator();

      final Receiver r = getCurrentlySelectedReceiver();
      add(createLevelRadioButton(r, Level.TRACE));
      add(createLevelRadioButton(r, Level.DEBUG));
      add(createLevelRadioButton(r, Level.INFO));
      add(createLevelRadioButton(r, Level.WARN));
      add(createLevelRadioButton(r, Level.ERROR));
      addSeparator();
      add(createLevelRadioButton(r, Level.OFF));
      add(createLevelRadioButton(r, Level.ALL));
      addSeparator();
      add(showReceiverHelpAction);
    }

    private JRadioButtonMenuItem createLevelRadioButton(
      final Receiver r, final Level l) {
      Map<String, Icon> levelIconMap = LevelIconFactory.getInstance().getLevelToIconMap();

      Action action =
        new AbstractAction(
          l.toString(), levelIconMap.get(l.toString())) {
          public void actionPerformed(ActionEvent e) {
            if (r != null) {
              r.setThreshold(l);
              updateCurrentlySelectedNodeInDispatchThread();
            }
          }
        };

      JRadioButtonMenuItem item = new JRadioButtonMenuItem(action);
      item.setSelected(r.getThreshold() == l);

      return item;
    }

    /**
     * Builds a relevant set of menus for when the Root node in the Receiver
     * tree has been selected
     *
     */
    private void buildForReceiversRoot() {
      JMenuItem startAll = new JMenuItem(startAllAction);

      add(newReceiverButtonAction);

      addSeparator();
      add(startAll);
    }
  }

  /**
   * A simple Panel that has toolbar buttons for restarting,
   * playing, pausing, and stoping receivers
   *
   * @author Paul Smith &lt;psmith@apache.org&gt;
   *
   */
  private class ReceiverToolbar extends JToolBar
    implements TreeSelectionListener {
    final SmallButton newReceiverButton;

    private ReceiverToolbar() {
      setFloatable(false);

      SmallButton restartReceiverButton = new SmallButton(restartReceiverButtonAction);
      restartReceiverButton.setText(null);
      
      SmallButton shutdownReceiverButton =
        new SmallButton(shutdownReceiverButtonAction);
      shutdownReceiverButton.setText(null);

      SmallButton saveReceiversButton =
        new SmallButton(saveReceiversButtonAction);
      saveReceiversButton.setText(null);

      SmallButton restartAllButton = new SmallButton(startAllAction);
      restartAllButton.setText(null);
      
      

      newReceiverButton = new SmallButton(newReceiverButtonAction);
      newReceiverButton.setText(null);
      newReceiverButton.addMouseListener(new PopupListener(newReceiverPopup));

      add(newReceiverButton);
      add(restartAllButton);

      addSeparator();

      add(restartReceiverButton);
      add(shutdownReceiverButton);
      add(saveReceiversButton);

      addSeparator();

      Action closeAction =
        new AbstractAction(null, LineIconFactory.createCloseIcon()) {
          public void actionPerformed(ActionEvent e) {
            ReceiversPanel.this.setVisible(false);
          }
        };

      closeAction.putValue(
        Action.SHORT_DESCRIPTION, "Closes the Receiver panel");

      add(Box.createHorizontalGlue());

      add(new SmallButton(closeAction));

      add(Box.createHorizontalStrut(5));
    }

    /**
     * Ensures the enabled property of the actions is set properly
     * according to the currently selected node in the tree
     */
    public void valueChanged(TreeSelectionEvent e) {
      updateActions();
    }
  }
}
