package internal.sim.sample_applet;

import javacard.framework.*;
import javacardx.framework.math.BCDUtil;
import uicc.toolkit.*;

public class SampleApplet extends Applet implements ToolkitInterface, ToolkitConstants {

    private ToolkitRegistry toolkitRegistry;
    private byte menuItem1;

    static final byte[] nvramText = {'N', 'V', 'R', 'A', 'M', ':', ' '};
    static final byte[] ramText = {'R', 'A', 'M', ':', ' '};
    static final byte[] menuItem1Text = {'D', 'e', 'b', 'u', 'g'};

    private byte[] debugBuffer;
    private short[] debugMemBuffer;
    private DiagUtil diag;

    private byte[] bcdBuffer;
    private byte[] tmpBuffer;

    public static void install(byte[] bArray, short bOffset, byte bLength) throws ISOException {
        SampleApplet sampleApplet = new SampleApplet();
        sampleApplet.register();

        sampleApplet.initUiccToolkit();
    }

    private void initUiccToolkit() {
        toolkitRegistry = ToolkitRegistrySystem.getEntry();

        menuItem1 = toolkitRegistry.initMenuEntry(menuItem1Text, (short) 0, (short) menuItem1Text.length,
            PRO_CMD_SELECT_ITEM, false, (byte) 0, (short) 0);
    }

    private SampleApplet() {
        diag = new DiagUtil();
        debugBuffer = JCSystem.makeTransientByteArray((short) 16, JCSystem.CLEAR_ON_RESET);
        debugMemBuffer = JCSystem.makeTransientShortArray((short) 2, JCSystem.CLEAR_ON_RESET);
        bcdBuffer = JCSystem.makeTransientByteArray((short) 10, JCSystem.CLEAR_ON_RESET);
        tmpBuffer = JCSystem.makeTransientByteArray((short) 64, JCSystem.CLEAR_ON_RESET);
    }

    public Shareable getShareableInterfaceObject(AID clientAID, byte parameter) {
        if (clientAID == null) {
            return this;
        }
        return null;
    }

    @Override
    public void process(APDU apdu) throws ISOException {

    }

    @Override
    public void processToolkit(short event) throws ToolkitException {
        // 本メソッドが例外を発生させても外部から観測できないため、デバッグが困難になります。
        // 必ず全ての例外をキャッチして、デバッグ用に記録するようにします。
        try {
            processToolkitEvent(event);
        } catch (UserException e) {
            Util.setShort(debugBuffer, (short) 4, e.getReason());
        } catch (ToolkitException e) {
            Util.setShort(debugBuffer, (short) 6, e.getReason());
            throw e;
        } catch (Exception e) {
            //その他の例外の発生回数を記録
            short i = Util.getShort(debugBuffer, (short) 2);
            Util.setShort(debugBuffer, (short) 2, (short) (i + 1));
        }
    }

    public void processToolkitEvent(short event) throws ToolkitException, UserException {
        if (event == EVENT_MENU_SELECTION) {
            // ユーザがSIM Toolkitアプリを端末上で開き、メニュー項目をタップすると呼ばれる
            EnvelopeHandler envHdlr = EnvelopeHandlerSystem.getTheHandler();
            byte selectedItemId = envHdlr.getItemIdentifier();

            if (selectedItemId == menuItem1) {
                DiagUtil.text(menuItem1Text); //'Debug'
                diag.displayBytes(debugBuffer, (short) 0, (short) debugBuffer.length);

                short pos, bcdBytes;
                //NVRAMの残量を表示
                JCSystem.getAvailableMemory(debugMemBuffer, (short) 0, JCSystem.MEMORY_TYPE_PERSISTENT);
                Util.setShort(bcdBuffer, (short) 0, debugMemBuffer[0]);
                Util.setShort(bcdBuffer, (short) 2, debugMemBuffer[1]);
                bcdBytes = BCDUtil.convertToBCD(bcdBuffer, (short) 0, (short) 4, bcdBuffer, (short) 0);
                pos = Util.arrayCopy(nvramText, (short) 0, tmpBuffer, (short) 0, (short) nvramText.length);
                pos = ByteUtil.bcdToCharArray(bcdBuffer, bcdBytes, tmpBuffer, pos);
                diag.text(tmpBuffer, (short) 0, pos);

                //RAMの残量を表示
                JCSystem.getAvailableMemory(debugMemBuffer, (short) 0, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
                Util.setShort(bcdBuffer, (short) 0, debugMemBuffer[0]);
                Util.setShort(bcdBuffer, (short) 2, debugMemBuffer[1]);
                bcdBytes = BCDUtil.convertToBCD(bcdBuffer, (short) 0, (short) 4, bcdBuffer, (short) 0);
                pos = Util.arrayCopy(ramText, (short) 0, tmpBuffer, (short) 0, (short) ramText.length);
                pos = ByteUtil.bcdToCharArray(bcdBuffer, bcdBytes, tmpBuffer, pos);
                diag.text(tmpBuffer, (short) 0, pos);
            }
        }

    }

}
