package org._1935711.gosia;

import org._1935711.gosia.Msx;

import javacard.framework.ISOException;
import javacard.framework.Applet;
import javacard.framework.JCSystem;
import javacard.framework.APDU;
import javacard.framework.ISO7816;
import javacard.framework.Util;

public class GosiaMsx extends Applet {
    private boolean pfailurePacket = false;
    private boolean pfailureMsx = false;
    private byte[] packetBuffer;

    Msx msx;

    private GosiaMsx() {
        try {
            packetBuffer = JCSystem.makeTransientByteArray(
                    Msx.MEMORY_SIZE,
                    JCSystem.CLEAR_ON_RESET);
        } catch (Exception e) {
            pfailurePacket = true;
        }
        try {
            msx = new Msx(packetBuffer);
        } catch (Exception e) {
            pfailureMsx = true;
        }
    }

    public static void install(final byte[] bArray, final short bOffset, final byte bLength) {
        GosiaMsx applet = new GosiaMsx();
        applet.register();
    }

    public void process(APDU apdu) throws ISOException {
        byte[] apduBuffer = apdu.getBuffer();
        if (this.selectingApplet()) {
            ISOException.throwIt(ISO7816.SW_NO_ERROR);
        } else if (!(this.pfailurePacket || pfailureMsx || apduBuffer.length < 5)) {
            final short ins = apduBuffer[ISO7816.OFFSET_INS];
            final short lc = apduBuffer[ISO7816.OFFSET_LC];

            switch (ins) {
                case Msx.APDU_INS_PLAY: {
                    short responseLengthExpected = apdu.setOutgoing();
                    apdu.setOutgoingLength(Msx.BLOCK_LENGTH);
                    final byte sampleIndex = msx.controlPlay(apduBuffer);
                    apdu.sendBytesLong(this.packetBuffer, (short) 0, Msx.BLOCK_LENGTH);
                    ISOException.throwIt((short) ((short) 0x9D00 | (short) sampleIndex));
                    break;
                }
                // case Msx.APDU_INS_LOAD_A0:
                case Msx.APDU_INS_LOAD_A1:
                case Msx.APDU_INS_LOAD_A2:
                case Msx.APDU_INS_LOAD_A3:
                case Msx.APDU_INS_LOAD_A4:
                case Msx.APDU_INS_LOAD_A5:
                    // case Msx.APDU_INS_LOAD_B0:
                case Msx.APDU_INS_LOAD_B1:
                case Msx.APDU_INS_LOAD_B2:
                case Msx.APDU_INS_LOAD_B3:
                case Msx.APDU_INS_LOAD_B4:
                case Msx.APDU_INS_LOAD_B5: {
                    short readCount = 0;
                    try {
                        readCount = apdu.setIncomingAndReceive();
                    } catch (Exception e) {
                        ISOException.throwIt((short) 0x9C01);
                    }
                    msx.controlLoad(apduBuffer, readCount);
                    apdu.setOutgoingAndSend((short) 0, (short) 0);
                    break;
                }
                default:
                    ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
                    break;
            }
        } else {
            ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
        }
    }
}
