package com.gemalto.examples;

/*
 * Imported packages
 */
import com.gemalto.examples.utility.FileAccessLibrary;

import sim.toolkit.*;
import sim.access.*;
import javacard.framework.*;

public class ZyrconCinemas extends javacard.framework.Applet implements
ToolkitInterface, ToolkitConstants {
	// Mandatory variables
	private SIMView gsmFile;

	private ToolkitRegistry reg;

	// Main Menu
	private byte idMenu1;

	private byte[] Menu1;

	private byte idMenu2;

	private byte[] Menu2;

	// Temporary buffer for storing intermediate data and results
	private byte[] tempBuffer;
	
	// Buffer for the FCI (File Control Information)
	private byte[] EFFciBuffer;

	/**
	 * Constructor of the applet
	 */
	public ZyrconCinemas() {
		// Get the GSM application reference
		gsmFile = SIMSystem.getTheSIMView();
		// Get the reference of the applet ToolkitRegistry object
		reg = ToolkitRegistry.getEntry();

		tempBuffer = JCSystem.makeTransientByteArray((short) 50,
				JCSystem.CLEAR_ON_RESET);
		/**@todo: Customize your menu titles here*/
		Menu1 = new byte[] { (byte) 'C', (byte) 'i', (byte) 'n', (byte) 'e',
				(byte) 'm', (byte) 'a', (byte) 's' };
		Menu2 = new byte[] { (byte) 'M', (byte) 'o', (byte) 'v', (byte) 'i',
				(byte) 'e', (byte) 's' };
		// Define the applet Menu Entry
		idMenu1 = reg.initMenuEntry(Menu1, (short) 0, (short) Menu1.length,
				PRO_CMD_SELECT_ITEM, false, (byte) 0, (short) 0);
		idMenu2 = reg.initMenuEntry(Menu2, (short) 0, (short) Menu2.length,
				(byte) 0, false, (byte) 0, (short) 0);
		// Define the Formatted SMS PP event that trigger the applet
		reg.setEvent(EVENT_FORMATTED_SMS_PP_ENV);
		
		// Initialize the FCI Buffer
		EFFciBuffer = new byte[22];

	}

	/**
	 * Method called by the JCRE at the installation of the applet
	 * @param bArray the byte array containing the AID bytes
	 * @param bOffset the start of AID bytes in bArray
	 * @param bLength the length of the AID bytes in bArray
	 */
	public static void install(byte[] bArray, short bOffset, byte bLength) {
		// Create the Java SIM toolkit applet
		ZyrconCinemas StkCommandsExampleApplet = new ZyrconCinemas();
		// Register this applet
		StkCommandsExampleApplet.register(bArray, (short) (bOffset + 1),
				(byte) bArray[bOffset]);
	}

	/**
	 * Method called by the SIM Toolkit Framework
	 * @param event the byte representation of the event triggered
	 */
	public void processToolkit(byte event) {
		EnvelopeHandler envHdlr = EnvelopeHandler.getTheHandler();

		// Manage the request following the MENU SELECTION event type
		if (event == EVENT_MENU_SELECTION) {
			// Get the selected item
			byte selectedItemId = envHdlr.getItemIdentifier();

			// Perform the required service following the Menu1 selected item
			if (selectedItemId == idMenu1) {
				menu1Action();
			}

			// Perform the required service following the Menu2 selected item
			if (selectedItemId == idMenu2) {
				menu2Action();
			}
		}
		// Manage the request following the FORMATTED SMS PP event type
		if (event == EVENT_FORMATTED_SMS_PP_ENV) {
			formattedSmsDownloadService();
		}
	}

	/**
	 * Method called by the JCRE, once selected
	 * @param apdu the incoming APDU object
	 */
	public void process(APDU apdu) {
		// ignore the applet select command dispached to the process
		if (selectingApplet()) {
			return;
		}
	}

	/**
	 * Manage the Menu1 selection
	 */
	private void menu1Action() {
		// Get the received envelope
		ProactiveHandler proHdlr = ProactiveHandler.getTheHandler();

		// Prepare the "Cinemas" STK Menu
		proHdlr.init(PRO_CMD_SELECT_ITEM, (byte) 0x00, (byte) ToolkitConstants.DEV_ID_ME);
		proHdlr.appendTLV((byte) (TAG_ALPHA_IDENTIFIER), Menu1, (short) 0x0000, (short) Menu1.length);

		// Reset the FCI Buffer
		resetBuffer(EFFciBuffer, (byte) 0x00);

		// Select ADN file and store ADN file properties in the FCI Buffer
		FileAccessLibrary.selectDF_telecom(gsmFile);
		FileAccessLibrary.selectEF(gsmFile, (short) 0x6F3A, EFFciBuffer);

		// Get the number of records and the length of each record
		short recCount = FileAccessLibrary.getLinearFileRecordNumber(EFFciBuffer);
		short recLength = FileAccessLibrary.getLinearFileRecordLength(EFFciBuffer);

		// Reset buffer
		resetBuffer(tempBuffer, (byte) 0xFF);

		// Append sub menu item for each record that not empty
		for (short i = 1; i <= recCount; i ++) {
			FileAccessLibrary.readRecord(gsmFile, i, tempBuffer, (short) recLength);
			if (!FileAccessLibrary.isEmptyRecord(tempBuffer)) {
				byte[] name = FileAccessLibrary.getNameFromAdnRecord(tempBuffer, recLength);
				proHdlr.appendTLV((byte) (TAG_ITEM), (byte) i, name, (short) 0x0000, (short) name.length);
			}
		}

		// select the MF to avoid locking the EF ADN
		FileAccessLibrary.selectMF(gsmFile);

		// send the proactive command
		proHdlr.send();

		return;
	}

	/**
	 * Manage the Menu2 selection
	 */
	private void menu2Action() {
		/**@todo: Replace following sample code with your implementation*/
		// Get the received envelope
		ProactiveHandler proHdlr = ProactiveHandler.getTheHandler();

		// Display the "Menu2" message text
		// Initialize the display text command
		proHdlr.initDisplayText((byte) 0x00, DCS_8_BIT_DATA, Menu2, (short) 0,
				(short) (Menu2.length));
		proHdlr.send();

		return;
	}

	/**
	 * Method illustrating the use of the FORMATTED SMS PP ENV event.
	 */
	private void formattedSmsDownloadService() {
		/**@todo: Replace following sample code with your implementation*/
		EnvelopeHandler envHdlr = EnvelopeHandler.getTheHandler();
		ProactiveHandler proHdlr = ProactiveHandler.getTheHandler();

		// Clear the temporary data buffer
		Util.arrayFillNonAtomic(tempBuffer, (short) 0,
				(short) tempBuffer.length, (byte) 0x00);

		// Copy the user data in tempBuffer[]
		tempBuffer[0] = (byte) envHdlr.getSecuredDataLength();
		envHdlr.copyValue(envHdlr.getSecuredDataOffset(), tempBuffer,
				(short) 1, (short) tempBuffer[0]);

		// Display the data recieved
		proHdlr.initDisplayText((byte) 0, DCS_8_BIT_DATA, tempBuffer,
				(short) 1, (short) tempBuffer[0]);
		proHdlr.send();
		return;
	}
	/**
	 * ========================== utility methods ==================================
	 */

	/**
	 * Call this method to reset the buffer, fill with 0x00
	 * 
	 * @param buffer the buffer to be reset
	 */
	private static void resetBuffer(byte[] buffer, byte fillingByte) {
		Util.arrayFillNonAtomic(buffer, (short) 0, (short) buffer.length, (byte) fillingByte);
	}

}
