
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import byucc.jhdl.apps.Viewers.SimControl.SimIndicatorComponent;
import byucc.jhdl.base.HWSystem;
import byucc.jhdl.util.cli.CLInterpreter;
import byucc.jhdl.util.cli.CLITextField;;

/** A custom viewer for the NetworkMonitor design.  This viewer
 * contains two GraphCanvas objects in a tabbed pane. The first
 * GraphCanvas shows the number of hits to addresses to count.  The
 * second GraphCanvas shows the number of hits to addresses to count
 * and block.  The viewer also has a text field for command input and
 * a single button that can be configured by an external class.
 * @author Anthony L. Slade */
public class MonitorViewerPanel extends JPanel 
  implements ActionListener {

  /** The text for the toCount tab title */
  public static final String TAB_TITLE_COUNT = "Counts = ";
  /** The text for the toBlock tab title */
  public static final String TAB_TITLE_BLOCK = "Blocks = ";

  /** Creates a new MonitorViewerPanel
   * @param hws the hardware system associated with the NetworkMonitor
   * circuit
   * @param interpreter the CLInterpreter for text commands
   * @param toCount the values of the addresses to count
   * @param toBlock the values of the addresses to count and block
   */
  public MonitorViewerPanel( HWSystem hws,
			     CLInterpreter interpreter,
			     int[] toCount,
			     int[] toBlock ) {
    BoxLayout layout = new BoxLayout(this,BoxLayout.Y_AXIS);
    setLayout(layout);

    // set up the GraphCanvas objects
    String[] toCountStr = new String[ toCount.length ],
      toBlockStr = new String[ toBlock.length ];
    Color[] blues = new Color[ toCount.length ],
      reds = new Color[ toBlock.length ];
    for ( int bi = 0; bi < toCount.length; ++bi ) {
      toCountStr[bi] = ""+toCount[bi];
      blues[bi] = Color.blue;
    }
    for ( int ri = 0; ri < toBlock.length; ++ri ) {
      toBlockStr[ri] = ""+toBlock[ri];
      reds[ri] = Color.red;
    }
    _countCanvas = new GraphCanvas( toCountStr,
				    new int[toCount.length],
				    blues,
				    "Addresses to count");
    _blockCanvas = new GraphCanvas( toBlockStr,
				    new int[toBlock.length],
				    reds,
				    "Addresses to block");


    // Put the GraphCanvas objects in a tabbed pane
    _tabs = new JTabbedPane();
    _tabs.addTab( TAB_TITLE_COUNT+0, new JScrollPane( _countCanvas ) );
    _tabs.addTab( TAB_TITLE_BLOCK+0, new JScrollPane( _blockCanvas ) );

    add( _tabs );

    // create a panel with a command line input text field and a
    // simulation indicator element
    JPanel commandPanel = new JPanel();
    commandPanel.add(new JLabel("Command"));
    JTextField clitextfield = new CLITextField( interpreter );
    commandPanel.add( clitextfield );
    SimIndicatorComponent simIndicator = new SimIndicatorComponent();
    commandPanel.add( simIndicator );
    hws.addSimulatorCallback( simIndicator );
    add(commandPanel);//,BorderLayout.SOUTH);

    // create and add a configurable button
    add(_actionButton = new JButton("Unnassigned Action Button"));
    _actionButton.addActionListener( this );
  }

  /** Listens to the button to translate into method calls for
   * the registered ButtonListener */
  public void actionPerformed(ActionEvent e) {
    try {
      _buttonListener.buttonPressed( e.getActionCommand() );
    } catch ( NullPointerException npe ) {}
  }

  /** Controller may set the button text and listener with this method
   * @param listener the new button listener, which includes the text
   * information */
  public void setActionButton( ButtonListener listener ) {
    _buttonListener = listener;
    try {
      _actionButton.setText( _buttonListener.getActionString() );
      _actionButton.setActionCommand( _buttonListener.getActionString() );
    } catch ( NullPointerException npe ) {}
  }

  /** Clears the values of both the count view and the block view to
   * zero */
  public void resetValues() {
    _blockCanvas.resetValues();
    _countCanvas.resetValues();
  }

  /** Sets the values to display on the graphs
   * @param index the index of the value to update
   * @param value the new value
   * @param blocked indicates if the value is on the blocked list
   * (true) or on the watch/count list (false) */
  public void setGraphValue( int index, int value, boolean blocked ) {
    if ( blocked )
      _blockCanvas.updateValue( index, value );
    else
      _countCanvas.updateValue( index, value );
  }

  /** Sets the total number of hit addresses, this is a label on the
   * JTabbedPane */
  public void setCountTotal( int total ) {
    _tabs.setTitleAt( 0, TAB_TITLE_COUNT+total );
  }

  /** Sets the total number of hit addresses blocked, this is a label
   * on the JTabbedPane */
  public void setBlockTotal( int total ) {
    _tabs.setTitleAt( 1, TAB_TITLE_BLOCK+total );
  }

  /** A configurable button.  The setActionButton method sets it up */
  private JButton _actionButton;
  /** The view for the number of hits to count */
  private GraphCanvas _countCanvas;
  /** The view for the number of hits to count and block */
  private GraphCanvas _blockCanvas;
  /** The tabbed pane containing the GraphCanvas objects.  We maintain
   * a reference to it so we can update the labels on the tabs with
   * the total number of hits. */
  private JTabbedPane _tabs;
  /** The listener to the configurable button */
  private ButtonListener _buttonListener;

} // end class MonitorViewerPanel
