package com.marinilli.b2.c5;

import javacard.framework.*;

/**
 * Chapter 5 - An example Java Card Applet
 * This applet writes back dummy byte sequences. It is meant to show the
 * Java Card applet development process only.
 *
 * @author Mauro Marinilli
 * @version 1.0
 */

public class CardTest extends Applet {

  //standard APDU input offset values
  public final static byte THIS_CLA = (byte)0x90;
  public final static byte  INITIALIZE_TRANSACTION = (byte)0x20;
  public final static byte  COMPLETE_TRANSACTION= (byte)0x22;
  public final static byte  INITIALIZE_UPDATE= (byte)0x24;
  public final static byte  COMPLETE_UPDATE= (byte)0x26;

  // dummy byte sequences returned by this applet
  private final static byte[] INIT_SEQUENCE = { (byte)0x1, (byte)0x2 };
  private final static byte[] COMPLETE_SEQUENCE = { (byte)0x1, (byte)0x3 };
  private final static byte[] INIT_UPDATE_SEQUENCE = { (byte)0x1, (byte)0x2, (byte)0x3 };
  private final static byte[] COMPLETE_UPDATE_SEQUENCE = { (byte)0x1, (byte)0x1 };

  /**
   * Constructor.
   * Only this class's install method can create the applet object.
   */
  private CardTest() {
    //perform some initialization here
    // ...
    register();//register this instance
  }

  /**
   * Installs this applet.
   * @param byteArray the array containing installation parameters
   * @param offset the starting offset in byteArray
   * @param length the length in bytes of the parameter data in byteArray
   */
  public static void install(byte[] byteArray, short offset, byte length) {
    new CardTest();
  }

  /**
   * Implementation  of the standard method for processing an incoming APDU.
   * @param apdu the incoming APDU
   * @exception ISOException with ISO 7816-4 response bytes
   */
  public void process(APDU apdu) {
    byte buffer[] = apdu.getBuffer();

    if (buffer[ISO7816.OFFSET_CLA] == THIS_CLA) {
      switch (buffer[ISO7816.OFFSET_INS])	{
        case INITIALIZE_TRANSACTION:
          writeBack(apdu, INIT_SEQUENCE);
          break;
        case COMPLETE_TRANSACTION:
          writeBack(apdu, COMPLETE_SEQUENCE);
          break;
        case INITIALIZE_UPDATE:
          writeBack(apdu, INIT_UPDATE_SEQUENCE);
          break;
        case COMPLETE_UPDATE:
          writeBack(apdu, COMPLETE_UPDATE_SEQUENCE);
          break;
        default:
          ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
      }
    }
  }

  /**
   * An example method that writes back a given byte array through the apdu.
   */
  protected void writeBack(APDU apdu, byte[] bytes) {
    byte buffer[] = apdu.getBuffer();

    // set apdu for data output
    apdu.setOutgoing();

    apdu.setOutgoingLength( (short) (3) );

    // output header
    apdu.sendBytes( (short)0, (short) 3);
    // writes data
    apdu.sendBytesLong( bytes, (short) 0, (short) 0 );
  }

}