package nxm.sys.libxm;

import java.awt.Button;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Method;

import javax.swing.JButton;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import nxm.sys.lib.Message;
import nxm.sys.lib.Midas;
import nxm.sys.lib.Shell;
import nxm.sys.lib.Table;

/** X-Midas Control
    @author  prp / J. Czechowski IV
*/
public class XControl implements ActionListener, ChangeListener {
  /** Midas Component to be analyzed */
  public Component myComp;
  /** name of component */
  public String name;
  /** Action message id */
  public int actionMsgID = 1;
  /** Change message id */
  public int changeMsgID = 1;

  /** XControl Default Constructor */
  public XControl() {
     this(null);
  }

  /** XControl Constructor
   *  @param cname the name of the component to be set
   */
  public XControl(String cname) {
    setComponent(cname);
  }

  /** Search for and initialize a Midas Component with a given name
   *  @param cname the name of the component to be set
   */
  public void setComponent(String cname) {
    name = null;
    myComp = null;

    if (cname == null) {
      return;
    }

    Midas midas = Shell.getSharedMidasContext();
    Object comp = midas.registry.get(cname);
    if (comp == null || !(comp instanceof Component)) {
      midas.warning("Could not find Component: " + cname);
      return;
    }
    myComp = (Component)comp;
    name = cname;
  }

  /** Adds a new ActionListener with a given id
   *  @param id the ActionListener id
   */
  public void addActionListener (int id) {
    if (myComp == null) {
      Shell.getSharedMidasContext().warning("No Component to listen");
      return;
    }
    try {
      Method m = myComp.getClass().getMethod("addActionListener", new Class<?>[] {ActionListener.class});
      if (m != null) {
        m.invoke(myComp, new Object[] {this});
      }
    } catch (Exception e) {
      System.out.println("We caught exception trying to add action listener: " + e);
    }
    actionMsgID = id;
  }

  /** Adds a new ChangeListener with a given id
   *  @param id the ChangeListener id
   */
  public void addChangeListener (int id) {
    if (myComp == null) {
      Shell.getSharedMidasContext().warning("No Component to listen");
      return;
    }
    try {
      Method m = myComp.getClass().getMethod("addChangeListener", new Class<?>[] {ChangeListener.class});
      if (m != null) {
        m.invoke(myComp, new Object[] {this});
      }
    } catch (Exception e) {
      System.out.println("We caught exception trying to add state changed listener: " + e);
    }
    changeMsgID = id;
  }

  public void actionPerformed(ActionEvent e) {
    // System.out.println("Got ActionEvent: " + e);
    boolean continueProcess = processActionEvent(e);
    if (!continueProcess) return;

    if (actionMsgID > 0) {
      Table data = new Table();
      Message msg = null;
      Object sender = e.getSource();
      if (sender instanceof Button || sender instanceof JButton) {
        data.put("ARGS", 2);
        data.put("TYPE", "AL");
        data.put("VAL1", name);
        data.put("VAL2", e.getModifiers());
        msg = new Message("BUTTON", 0, data);
      } else {
        data.put("ARGS", 2);
        data.put("TYPE", "AL");
        data.put("VAL1", name);
        data.put("VAL2", 0);
        msg = new Message("ACTION", 0, data);
      }
      XmShellParent.sendXmMessage(actionMsgID, msg);
    }
  }

  public void stateChanged(ChangeEvent e) {
    // System.out.println("Got ChangeEvent: " + e);
    boolean continueProcess = processChangeEvent(e);
    if (!continueProcess) return;

    if (changeMsgID > 0) {
      Table data = new Table();
      Message msg = null;
      data.put("ARGS", 2);
      data.put("TYPE", "AL");
      data.put("VAL1", name);
      data.put("VAL2", 0);
      msg = new Message("CHANGE", 0, data);
      XmShellParent.sendXmMessage(changeMsgID, msg);
    }
  }

  /** Event handler for processing ActionEvents
   *  TODO: not yet implemented ??
   *  @param e the ActionEvent
   *  @return true
   */
  public boolean processActionEvent(ActionEvent e) {
    // override this method to handle ActionEvents in Java
    return true;
  }

  /** Event handler for processing ChangeEvents
   *  TODO: not yet implemented ??
   *  @param e the ChangeEvent
   *  @return true
   */
  public boolean processChangeEvent(ChangeEvent e) {
    // override this method to handle ChangeEvents in Java
    return true;
  }

}
