package com.ibm.able.examples.ableagent;

//====================================================================
//
// Licensed Materials - Property of IBM
//
// "Restricted Materials of IBM"
//
// Product: com.ibm.able.examples.ableagent
//
// (C) Copyright IBM Corp. 2000 All Rights Reserved.
//
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with
// IBM Corp.
//
//
//                             DISCLAIMER
//                             ----------
//
// This material contains programming source code for your consideration.
// These examples have not been thoroughly tested under all conditions.
// IBM, therefore, cannot guarantee or imply reliability, serviceability,
// performance or function of these programs.  All programs contained
// herein are provided to you "AS IS".  THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
// DISCLAIMED.
//
//====================================================================

//====================================================================
// Imports
//====================================================================
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.net.URL;
import java.rmi.RemoteException;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.UIManager;

import com.ibm.able.Able;
import com.ibm.able.AbleCustomizerPanel;
import com.ibm.able.AbleDefaultAgentCustomizer;
import com.ibm.able.AbleHelp;
import com.ibm.able.AblePanelHelper;

/**
 * This class provides the customizer for the Simple Able Agent.
 *
 * @see com.ibm.able.AbleDefaultAgentCustomizer
 * @see SimpleAbleAgentPanel
 *
 * @version  $Revision: 1.14 $, $Date: 2001/09/17 21:47:47 $
 *
 * @author   Joe Bigus
 */
public class SimpleAbleAgentCustomizer extends AbleDefaultAgentCustomizer {

   //-----------------------------------------------------------------
   // Member variables
   //-----------------------------------------------------------------
   private SimpleAbleAgentPanel myAgentPanel = null;

   //-----------------------------------------------------------------
   // Constructors
   //-----------------------------------------------------------------
   /**
    *  Construct a Simple Able Agent Customizer dialog.  Dialog is
    *  not modal so other windows can be active at the same time.
    *
    * @param theFrame The frame from which the dialog is displayed.
    * @param theTitle The default name to display in the dialog's title bar.
    *              This will be replaced with the object name when the object is set.
    */
   public SimpleAbleAgentCustomizer(JFrame theFrame, String theTitle) {
      super(theFrame, theTitle, false); // non-modal
      // pass this customizer to the base customizer so OK calls this.updateObject
      setCustomizer(this);
      // create the panel;  pass this customizer so it can call this.updateObject too
      // and so it can register property listeners with the base customizer
      myAgentPanel = new SimpleAbleAgentPanel(this);
      insertTab("Simple Able Agent", myAgentPanel, 1);
   }

   /**
    *  Construct a Simple Able Agent Customizer Dialog.  Dialog is
    *  not modal so other windows can be active at the same time.
    *
    */
   public SimpleAbleAgentCustomizer() {
      this(new JFrame(), "Simple Able Agent Customizer");
   }

   //-----------------------------------------------------------------
   // Main method
   //-----------------------------------------------------------------
   /**
    *  The main method is provided only for testing.
    *
    */
   static public void main(String args[]) {
      try {
         UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
         SimpleAbleAgentCustomizer c = new SimpleAbleAgentCustomizer();
         c.setObject(new SimpleAbleAgent());
         c.setVisible(true);
      } catch (Exception e) {
         JOptionPane.showMessageDialog(null, // Parent
         e.toString(), // Msg
         "SimpleAbleAgentCustomizer()", // Title
         JOptionPane.ERROR_MESSAGE // Severity
         );
      }
   }

   //--------------------------------------------------------------------
   // Methods inherited from Customizer interface
   //--------------------------------------------------------------------

   /**
    * Write the data from the object to the panel(s) provided
    * by this customizer. The panel saves a reference to the
    * agent being customized.
    * Pass the object and its data to any inherited panel.
    *
    * @param     anAgent
    *            The Agent that is to be changed.
    * @see com.ibm.able.AbleObjectCustomizer
    */
   public void setObject(Object anAgent) {
      super.setObject(anAgent);
      try {
         myAgentPanel.getDataFromBean((SimpleAbleAgent) anAgent);
      } catch (RemoteException e) {
         JOptionPane.showMessageDialog(this, // Parent
         e.toString(), // Msg
         "SimpleAbleAgentCustomizer Error: setObject()", // Title
         JOptionPane.ERROR_MESSAGE // Severity
         );
      }
   }

   /**
    * Update the agent that is being customized.  This method is
    * called when the dialog's OK button is pressed.
    *
    * @exception RemoteException is thrown when the panel values
    *            cannot be set on the agent.
    */
   public void updateObject() throws RemoteException {
      super.updateObject();
      myAgentPanel.setDataOnBean();
   }

   /**
    * This class provides the panel for the simple Able Agent tab.
    *
    * @see com.ibm.able.AbleObjectCustomizer
    * @see com.ibm.able.AbleDefaultAgentCustomizer
    * @see SimpleAbleAgentCustomizer
    *
    * @version  $Revision: 1.14 $, $Date: 2001/09/17 21:47:47 $
    *
    * @author   Joe Bigus
    */
   public class SimpleAbleAgentPanel
      extends JPanel
      implements AbleCustomizerPanel {

      //-----------------------------------------------------------------
      // Member variables
      //-----------------------------------------------------------------
      private SimpleAbleAgent myAgent = null;
      private SimpleAbleAgentCustomizer myCustomizer = null;

      private JComboBox myColorComboBox = null;

      //-----------------------------------------------------------------
      // Constructors
      //-----------------------------------------------------------------
      /**
       *  No default constructor allowed.
       */
      public SimpleAbleAgentPanel() {
      }

      /**
       * Construct the panel for the customizer.
       *
       * @param theCustomizer The customizer reference is provided because
       *                      this will be used to register property change
       *                      listeners, read all the property panels before
       *                      updating the object, and update all the property
       *                      panels when a refresh is needed.
       */
      public SimpleAbleAgentPanel(SimpleAbleAgentCustomizer theCustomizer) {
         super();
         myCustomizer = theCustomizer;
         this.setLayout(null);
         initializePanel();
         addPropertyListeners();
      }

      //-----------------------------------------------------------------
      // Member methods
      //-----------------------------------------------------------------
      /**
       * Save a reference to the agent that is being customized.
       * Get the data from the bean and set the panel components.
       *
       * @param     anAgent
       *            The SimpleAbleAgent Agent that is to be changed.
       * @exception RemoteException is thrown when data cannot be retrieved
       *            from a remote agent.
       */
      public void getDataFromBean(Object anAgent) throws RemoteException {
         if (myAgent == null) {
            // null if initial call - otherwise, this is just a reset
            myAgent = (SimpleAbleAgent) anAgent;
         }

         myColorComboBox.setSelectedItem(myAgent.getSimpleBeanColor());
      }

      /**
       * Update the agent that is being customized.
       *
       * @exception RemoteException is thrown when data cannot be set
       *            on a remote agent.
       */
      public void setDataOnBean() throws RemoteException {
         try {
            myAgent.setSimpleBeanColor(
               (String) myColorComboBox.getSelectedItem());
         } catch (NumberFormatException e) {
            throw new RemoteException(
               "Non-numeric input provided on Simple Agent panel."
                  + Able.LS
                  + e.toString());
         } catch (NullPointerException e2) {
            throw new RemoteException(
               "Blank input provided on Simple Agent panel."
                  + Able.LS
                  + e2.toString());
         }
      }

      /**
       * Initialize the panel.
       *
       */
      private void initializePanel() {
         this.setLayout(new BorderLayout(0, 0));
         JPanel ulPanel = new JPanel();
         ulPanel.add(new JLabel("Color:"));
         JPanel urPanel = new JPanel();
         myColorComboBox = new JComboBox();
         for (int i = 0; i < SimpleAbleAgent.colors.length; i++) {
            myColorComboBox.addItem(SimpleAbleAgent.colors[i]);
         }
         urPanel.add(myColorComboBox);
         JPanel upperPanel = new JPanel();
         upperPanel.add(ulPanel, BorderLayout.EAST);
         upperPanel.add(urPanel, BorderLayout.WEST);
         this.add(upperPanel, BorderLayout.NORTH);
         JPanel lowerPanel = new JPanel();
         AblePanelHelper.addButton(lowerPanel, "Reset", (new ActionListener() {
            public void actionPerformed(ActionEvent e) {
               ResetButton_actionPerformed(e);
            }
         }), "Reset the simple agent");
         this.add(lowerPanel, BorderLayout.SOUTH);

      }

      /**
       *  Anytime another application or another panel changes the training
       *  property, refresh this panel.
       *
       */
      private void addPropertyListeners() {
         myCustomizer.addPropertyChangeMethod(
            "simpleBeanColor",
            this,
            "refreshPanel");
      }

      /**
       *  Refresh the panel on specific property change events.
       *
       *  @see com.ibm.able.AbleObjectCustomizer
       *  @param theEvent is the event issued when an agent's property changes.
       */
      public void refreshPanel(PropertyChangeEvent theEvent) {
         try {
            getDataFromBean(myAgent);
         } catch (RemoteException e) {
            JOptionPane.showMessageDialog(myCustomizer, // Parent
            "Panel values for training changed, but were not updated."
               + Able.LS
               + e.toString(),
            // Msg
            "AbleNeuralClassifierAgentPanel Warning: refreshPanel()", // Title
            JOptionPane.WARNING_MESSAGE // Severity
            );
         }
      }

      //-----------------------------------------------------------------
      // Action methods
      //-----------------------------------------------------------------

      /**
       *  Perform the reset on the object.
       *
       *  @param theEvent the button pressed event.
       */
      void ResetButton_actionPerformed(ActionEvent theEvent) {
         try {
            // call the customizer to update the object in order to
            // prevent this panel from receiving any property changes
            // when the object is changed;  setDataOnBean would have
            // read just this panel and caused a property change
            myCustomizer.updateProperties();
            myCustomizer.setIgnoreAnyPropertyChanges(true);
            // perform the action, which may cause side effects
            // which we'll ignore because we intend to refresh the
            // customizer in a bit
            myAgent.reset();
            myCustomizer.setIgnoreAnyPropertyChanges(false);
            // read the object and update all the panels since the
            // action requested may have had side effects that change
            // values on other panels;  this refreshes all the panels
            // in contrast to getDataFromBean(myAgent) which would have
            // only refreshed the data displayed on this panel.
            myCustomizer.setObject(myAgent);

         } catch (Exception exc) {
            JOptionPane.showMessageDialog(this, // Parent
            exc.toString(), // Msg
            "SimpleAbleAgentCustomizer Error: ResetButton()", // Title
            JOptionPane.ERROR_MESSAGE // Severity
            );
         }
      }

      //------------------------------------------------------------------
      // Required by AbleCustomizerPanel interface
      //------------------------------------------------------------------

      /**
       * Get the html file name to be displayed.
       *
       * @return A String containing the html file to display in the browser.
       */
      public String getHelpFileName() {
         return AbleHelp.helpFilesPath
            + "examples/ableagent/doc-files/SimpleAbleAgentHelp.html";
      }

      /** Get the URL file context to be displayed. Able.HomeUrl is the
       * Able context.
       *
       * @see Able
       *
       * @return A URL containing the html file to display in the browser.
       */
      public URL getHelpContext() {
         return Able.HomeUrl;
      }

      /**
           *  Refresh the panel when the color property changes.
           *
           *  @param theEvent is the event issued when an agent's property changes.
           */
      class ObjectPropertyChangeListener implements PropertyChangeListener {
         public void propertyChange(PropertyChangeEvent theEvent) {
            try {
               if (theEvent != null
                  && theEvent.getPropertyName().equals("simpleBeanColor")) {
                  getDataFromBean(myAgent);
               }
            } catch (RemoteException e) {
            }
         }

      }
   }

   /**
    * Determine the copyright of this class.
    *
    * @return    A String containing this class's copyright statement.
    *            <p>
    */
   private static String Copyright() {
      return Able.Copyright;
   }

}
