package applet;

import javacard.framework.ISOException;
import javacard.framework.Util;

public class TLVHelper {

    /**
     * Decode TLV length field according to ts_102221 11.3,0
     */
    public static short getLengthFieldValue(byte[] tlv, short offset) throws IllegalArgumentsException {
        if (tlv[offset] == (byte) 0x82) {
            if (tlv[(short) (offset + 1)] < 0) {
                throw IllegalArgumentsException.getException();
            }
            return Util.getShort(tlv, (short) (offset + 1));
        } else if (tlv[offset] == (byte) 0x81) {
            return (short) (0x00FF & tlv[(short) (offset + 1)]);
        } else if (tlv[offset] > 0) {
            return (short) (0x007F & tlv[offset]);
        } else if (tlv[offset] == 0) {
            return (short) 0;
        } else {
            throw IllegalArgumentsException.getException();
        }
    }

    public static short getLengthFieldLength(short length) {
        if (length < 128) {
            return 1;
        } else if (length < 256) {
            return 2;
        } else {
            return 3;
        }
    }

    public static short findTag(byte[] tlv, short offset, short length, byte tag) throws IllegalArgumentsException {
        short pos = offset;
        short len;

        while (pos < (short) (length + offset - 1)) {
            if (tlv[pos] == tag) {
                return pos;
            }
            len = getLengthFieldValue(tlv, (short) (pos + 1));
            pos += 1 + getLengthFieldLength(len) + len;
        }
        // 9404: Comparison pattern (Tag) not found.
        ISOException.throwIt((short) 37892);
        return pos;
    }

    public static boolean TLVNotValid(byte[] tlv, short offset, short length) {
        short pos = offset;
        short len;

        while (pos < (short) (length + offset - 1)) {
            try {
                len = getLengthFieldValue(tlv, (short) (pos + 1));
                pos += 1 + getLengthFieldLength(len) + len;
            } catch (IllegalArgumentsException e) {
                return true;
            }
        }
        return (pos != (short) (offset + length));
    }
}