package context.arch.generator;

import java.util.Date;
import java.util.Vector;
import java.util.Hashtable;

import com.ibutton.oc.JibMultiListener;
import com.ibutton.oc.JibMultiFactory;
import com.ibutton.oc.JibMultiEvent;
import com.ibutton.oc.terminal.jib.iButtonCardTerminal;
import opencard.core.terminal.SlotChannel;
import opencard.core.terminal.CardTerminalException;

import context.arch.widget.Widget;

/**
 * This class acts as a wrapper around a Java iButton reader.  Whenever
 * an iButton docks with the reader, the location of the reader, the
 * iButton id and the docking timestamp are stored and made available
 * to the context-aware infrastructure for polling, and can notify 
 * context widgets when data changes.
 *
 * @see com.ibutton.oc.JibMultiListener
 * @see context.arch.widget.Widget
 */
public class PositionIButton implements JibMultiListener {

  /**
   * Debug flag. Set to true to see debug messages.
   */
  private static final boolean DEBUG = false;

  private String location = ""; 
  private String currentid = "";
  private long currentTime = 0;
  private Widget widget = null;

  /**
   * Constructor that allows this object to handle iButton events and
   * starts listening to the iButton reader.  It sets the location of
   * the IButton reader and sets the context widget to notify when an
   * IButton docks.
   *
   * @param widget Widget to notify when an IButton docks
   * @param location Place where this iButton reader is installed
   * @see com.ibutton.oc.JibMultiFactory
   * @see com.ibutton.oc.JibMultiFactory#addJiBListener(com.ibutton.oc.terminal.jib.JibMultiListener)
   * @see com.ibutton.oc.JibMultiFactory#startPolling(boolean)
   */
  public PositionIButton(Widget widget, String location) {
    this.widget = widget;
    this.location = location;
    JibMultiFactory jibFactory = new JibMultiFactory();
    
    /* Add myself to the listener. */
    jibFactory.addJiBListener(this);

    /* Start the polling thread.
       Set to true to use opencard.properties.
       Set to false to enumerate the ports through JibMultiListener.
    */
    try {
      jibFactory.startPolling(true);
    } catch (CardTerminalException cte) {
        System.out.println ("PositionIButton CardTerminalException: "+cte);
    }
  }

  /**
   * Constructor that allows this object to handle iButton events and
   * starts listening to the iButton reader.  It sets the location of the
   * IButton reader.
   *
   * @param location Place where this iButton reader is installed
   */
  public PositionIButton(String location) {
    this(null,location);
  }

  /** 
   * This method is called by the card terminal driver to let us know that a
   * Button insertion has been detected.  It stores the information locally
   * and notifies the registered Widget object, if available, of the
   * new data.
   *
   * @param event Event that indicates an iButton has been inserted
   * @see context.arch.widget.Widget#notify(java.lang.String,java.lang.Object)
   * @see com.ibutton.oc.terminal.jib.JibMultiEvent
   */
  public void iButtonInserted(JibMultiEvent event) {
    String buttonstr;
        
    /* Get a reference to the communications path the event came from. */
    SlotChannel channel = event.getChannel();

    /* Get a reference to the driver for the terminal. */
    iButtonCardTerminal ct = (iButtonCardTerminal)channel.getCardTerminal();
    
    /* Get the iButton ID from the slot. */
    int[] iButtonId = ct.getiButtonId(event.getSlotID());
    
    currentid = toHexString(iButtonId);
    currentTime = new Date().getTime();

    if (DEBUG) {
      System.out.println(currentid +" has been docked");
    }

    if (widget != null) {
      widget.notify(Widget.UPDATE, new IButtonData(location, currentid, Long.toString(currentTime)));
    }
  }

  /** 
   * This method is called by the card terminal driver to let us know that a
   * Button removal has been detected.  It just prints a message to
   * the screen.
   *
   * @param event Event that indicates an iButton has been removed
   * @see com.ibutton.oc.terminal.jib.JibMultiEvent
   */
  public void iButtonRemoved(JibMultiEvent event) {
    if (DEBUG) {
      System.out.println("iButton has been removed");
    }
  }

  /** 
   * This private method converts the given int array into a hex 
   * string array.
   *
   * @param arr Int array to convert to hex
   * @return Hex string to convert int array from
   */
  private String toHexString(int[] arr) {
    String str = "";
    for (int i = 0;i < arr.length;i++) {
      if (arr[i] < 0x10) {
        str += "0";
      }
      str += Integer.toHexString(arr[i]).toUpperCase();
    }
    return str;
  }

  /**
   * This method supports polling of the IButton data. It returns an IButtonData object
   * containing the most recent docking information.
   *
   * @return IButtonData object containing the most recent docking information
   */
  public IButtonData pollData() {
    IButtonData data = new IButtonData(location, currentid, Long.toString(currentTime));
    return data;
  }
}
