public class CMIBlock extends InterpretedBlock {

	public ByteString mCardSerialNumber;
	public ByteString mCardSerialNumberCheckByte;
	public ByteString mManufacturerData;

	public CMIBlock(byte[] bits) {
		super("CMI", bits);

		mCardSerialNumber = new ByteString(32, true);
		mCardSerialNumberCheckByte = new ByteString(8, true);
		mManufacturerData = new ByteString(88, true);

		mFields = new DataType[] {
			mCardSerialNumber,
			mCardSerialNumberCheckByte,
			mManufacturerData
		};
        mFieldNames = new String[] {
			"CardSerialNumber",
			"CardSerialNumberCheckByte",
			"ManufacturerData"
        };

		interpretBlock();
	}
} public class CommonTCSTBlock extends InterpretedBlock {

	public ByteString mIdentifier;
	public RKFInteger mVersionNumber;

	public CommonTCSTBlock(byte[] bits) {
		super("CommonTCST", bits);

		mIdentifier = new ByteString(8, false);
		mVersionNumber = new RKFInteger(6, true);

		mFields = new DataType[] {
			mIdentifier,
			mVersionNumber
		};
        mFieldNames = new String[] {
			"Identifier",
			"VersionNumber"
        };

		interpretBlock();
	}
} public class InterpretedBlock {

	public DataType[] mFields;
	public String[] mFieldNames;
	public byte[] mBits;
	public String id;
	
	public InterpretedBlock(String pid, byte[] bits) {
		id = pid;
		mBits = bits;
		assert bits.length == 16;
	}
	
	protected void interpretBlock() {
		int i = 0;
		String bitstring = DataType.getBinaryString(mBits);
		
		//Fix the endianness - reverse each byte
		StringBuilder sb = new StringBuilder();
		for (int j = 0; j < bitstring.length(); j += 8) {
			sb.append(new StringBuilder(bitstring.substring(j, j+8)).reverse().toString());
		}
		bitstring = sb.toString();
		assert(bitstring.length() == 128);
		//bitstring = new StringBuilder(bitstring).reverse().toString();
		
		for (DataType f : mFields) {
			int len = f.mBitlength;
			//Extract bits i:len
			try {
				String substr = bitstring.substring(i, i+len);
				f.fromBits(substr);
				i += len;
			}
			catch (StringIndexOutOfBoundsException e) {
				break;
			}
		}
	}
	
	public String toString() {
		StringBuilder sb = new StringBuilder();
		
		for (int i = 0; i < mFields.length; i++) {
			DataType f = mFields[i];
			String n = mFieldNames[i];
			sb.append(n);
			sb.append(": ");
			sb.append(f.toString());
			sb.append("\n");
		}
		
		return sb.toString();
	}

} public class TCAS1Block extends InterpretedBlock {

	public ByteString mIdentifier;
	public ByteString mVersionNumber;
	public RKFInteger mSectorStatus0;
	public RKFInteger mSectorStatus1;
	public RKFInteger mSectorStatus2;
	public RKFInteger mSectorStatus3;
	public RKFInteger mSectorStatus4;
	public RKFInteger mSectorStatus5;
	public RKFInteger mSectorStatus6;
	public RKFInteger mSectorStatus7;
	public RKFInteger mSectorStatus8;
	public RKFInteger mSectorStatus9;
	public RKFInteger mSectorStatus10;
	public RKFInteger mSectorStatus11;
	public RKFInteger mSectorStatus12;
	public RKFInteger mSectorStatus13;
	public RKFInteger mSectorStatus14;
	public RKFInteger mSectorStatus15;
	public RKFInteger mTransactionNumber;
	public RKFInteger mEventLogRecordNumber;
	public RKFInteger mTicketLogAreaSectorPointer;
	public RKFInteger mTicketLogSectorPointer1;
	public RKFInteger mTicketLogSectorPointer2;
	public RKFInteger mTicketLogSectorPointer3;
	public RKFInteger mTicketLogSectorPointer4;
	public RKFInteger mTicketLogSectorPointer5;
	public RKFInteger mTicketLogSectorPointer6;
	public RKFInteger mTicketLogSectorPointer7;
	public RKFInteger mTicketLogSectorPointer8;
	public ByteString mMACAlgorithmIdentifier;
	public ByteString mMACKeyIdentifier;
	public ByteString mMACAuthenticator;
	public ByteString mUnused;

	public TCAS1Block(byte[] bits) {
		super("TCAS1", bits);

		mIdentifier = new ByteString(8, true);
		mVersionNumber = new ByteString(6, true);
		mSectorStatus0 = new RKFInteger(2, true);
		mSectorStatus1 = new RKFInteger(2, true);
		mSectorStatus2 = new RKFInteger(2, true);
		mSectorStatus3 = new RKFInteger(2, true);
		mSectorStatus4 = new RKFInteger(2, true);
		mSectorStatus5 = new RKFInteger(2, true);
		mSectorStatus6 = new RKFInteger(2, true);
		mSectorStatus7 = new RKFInteger(2, true);
		mSectorStatus8 = new RKFInteger(2, true);
		mSectorStatus9 = new RKFInteger(2, true);
		mSectorStatus10 = new RKFInteger(2, true);
		mSectorStatus11 = new RKFInteger(2, true);
		mSectorStatus12 = new RKFInteger(2, true);
		mSectorStatus13 = new RKFInteger(2, true);
		mSectorStatus14 = new RKFInteger(2, true);
		mSectorStatus15 = new RKFInteger(2, true);
		mTransactionNumber = new RKFInteger(8, true);
		mEventLogRecordNumber = new RKFInteger(4, true);
		mTicketLogAreaSectorPointer = new RKFInteger(4, true);
		mTicketLogSectorPointer1 = new RKFInteger(4, true);
		mTicketLogSectorPointer2 = new RKFInteger(4, true);
		mTicketLogSectorPointer3 = new RKFInteger(4, true);
		mTicketLogSectorPointer4 = new RKFInteger(4, true);
		mTicketLogSectorPointer5 = new RKFInteger(4, true);
		mTicketLogSectorPointer6 = new RKFInteger(4, true);
		mTicketLogSectorPointer7 = new RKFInteger(4, true);
		mTicketLogSectorPointer8 = new RKFInteger(4, true);
		mMACAlgorithmIdentifier = new ByteString(2, true);
		mMACKeyIdentifier = new ByteString(6, true);
		mMACAuthenticator = new ByteString(16, true);
		mUnused = new ByteString(10, true);

		mFields = new DataType[] {
			mIdentifier,
			mVersionNumber,
			mSectorStatus0,
			mSectorStatus1,
			mSectorStatus2,
			mSectorStatus3,
			mSectorStatus4,
			mSectorStatus5,
			mSectorStatus6,
			mSectorStatus7,
			mSectorStatus8,
			mSectorStatus9,
			mSectorStatus10,
			mSectorStatus11,
			mSectorStatus12,
			mSectorStatus13,
			mSectorStatus14,
			mSectorStatus15,
			mTransactionNumber,
			mEventLogRecordNumber,
			mTicketLogAreaSectorPointer,
			mTicketLogSectorPointer1,
			mTicketLogSectorPointer2,
			mTicketLogSectorPointer3,
			mTicketLogSectorPointer4,
			mTicketLogSectorPointer5,
			mTicketLogSectorPointer6,
			mTicketLogSectorPointer7,
			mTicketLogSectorPointer8,
			mMACAlgorithmIdentifier,
			mMACKeyIdentifier,
			mMACAuthenticator,
			mUnused
		};
        mFieldNames = new String[] {
			"Identifier",
			"VersionNumber",
			"SectorStatus0",
			"SectorStatus1",
			"SectorStatus2",
			"SectorStatus3",
			"SectorStatus4",
			"SectorStatus5",
			"SectorStatus6",
			"SectorStatus7",
			"SectorStatus8",
			"SectorStatus9",
			"SectorStatus10",
			"SectorStatus11",
			"SectorStatus12",
			"SectorStatus13",
			"SectorStatus14",
			"SectorStatus15",
			"TransactionNumber",
			"EventLogRecordNumber",
			"TicketLogAreaSectorPointer",
			"TicketLogSectorPointer1",
			"TicketLogSectorPointer2",
			"TicketLogSectorPointer3",
			"TicketLogSectorPointer4",
			"TicketLogSectorPointer5",
			"TicketLogSectorPointer6",
			"TicketLogSectorPointer7",
			"TicketLogSectorPointer8",
			"MACAlgorithmIdentifier",
			"MACKeyIdentifier",
			"MACAuthenticator",
			"Unused"
        };

		interpretBlock();
	}
} public class TCCIBlock extends InterpretedBlock {

	public ByteString mMADInfoByte;
	public RKFInteger mCardVersion;
	public ByteString mCardProvider;
	public DateCompact mCardValidityEndDate;
	public ByteString mCardStatus;
	public RKFInteger mCardCurrencyUnit;
	public RKFInteger mEventLogVersionNumber;
	public ByteString mMACAlgorithmIdentifier;
	public ByteString mMACKeyIdentifier;
	public ByteString mMACAuthenticator;
	public ByteString mUnused;

	public TCCIBlock(byte[] bits) {
		super("TCCI", bits);

		mMADInfoByte = new ByteString(16, true);
		mCardVersion = new RKFInteger(6, true);
		mCardProvider = new ByteString(12, true);
		mCardValidityEndDate = new DateCompact(14, true);
		mCardStatus = new ByteString(8, true);
		mCardCurrencyUnit = new RKFInteger(16, true);
		mEventLogVersionNumber = new RKFInteger(6, true);
		mMACAlgorithmIdentifier = new ByteString(2, true);
		mMACKeyIdentifier = new ByteString(6, true);
		mMACAuthenticator = new ByteString(16, true);
		mUnused = new ByteString(26, true);

		mFields = new DataType[] {
			mMADInfoByte,
			mCardVersion,
			mCardProvider,
			mCardValidityEndDate,
			mCardStatus,
			mCardCurrencyUnit,
			mEventLogVersionNumber,
			mMACAlgorithmIdentifier,
			mMACKeyIdentifier,
			mMACAuthenticator,
			mUnused
		};
        mFieldNames = new String[] {
			"MADInfoByte",
			"CardVersion",
			"CardProvider",
			"CardValidityEndDate",
			"CardStatus",
			"CardCurrencyUnit",
			"EventLogVersionNumber",
			"MACAlgorithmIdentifier",
			"MACKeyIdentifier",
			"MACAuthenticator",
			"Unused"
        };

		interpretBlock();
	}
} public class TCCPStaticBlock extends InterpretedBlock {

	public ByteString mIdentifier;
	public RKFInteger mVersionNumber;
	public ByteString mAID;
	public ByteString mStatus;
	public RKFInteger mCustomerNumber;
	public ByteString mXXX1;
	public RKFInteger mSequenceNumber;
	public ByteString mXXX2;
	public DateMonth11 mBirthday;
	public ByteString mXXX;

	public TCCPStaticBlock(byte[] bits) {
		super("TCCPStatic", bits);

		mIdentifier = new ByteString(8, false);
		mVersionNumber = new RKFInteger(6, true);
		mAID = new ByteString(12, true);
		mStatus = new ByteString(8, true);
		mCustomerNumber = new RKFInteger(34, true);
		mXXX1 = new ByteString(61, true);
		mSequenceNumber = new RKFInteger(8, true);
		mXXX2 = new ByteString(23, true);
		mBirthday = new DateMonth11(11, true);
		mXXX = new ByteString(256, true);

		mFields = new DataType[] {
			mIdentifier,
			mVersionNumber,
			mAID,
			mStatus,
			mCustomerNumber,
			mXXX1,
			mSequenceNumber,
			mXXX2,
			mBirthday,
			mXXX
		};
        mFieldNames = new String[] {
			"Identifier",
			"VersionNumber",
			"AID",
			"Status",
			"CustomerNumber",
			"XXX1",
			"SequenceNumber",
			"XXX2",
			"Birthday",
			"XXX"
        };

		interpretBlock();
	}
} public class TCDBDynamicBlock extends InterpretedBlock {

	public ByteString mStatus;
	public DateMonth8 mFirsthMonth;
	public ByteString mXXX1;
	public RKFInteger mDiscountStep;
	public ByteString mXXX;

	public TCDBDynamicBlock(byte[] bits) {
		super("TCDBDynamic", bits);

		mStatus = new ByteString(8, true);
		mFirsthMonth = new DateMonth8(8, true);
		mXXX1 = new ByteString(55, true);
		mDiscountStep = new RKFInteger(8, true);
		mXXX = new ByteString(128, true);

		mFields = new DataType[] {
			mStatus,
			mFirsthMonth,
			mXXX1,
			mDiscountStep,
			mXXX
		};
        mFieldNames = new String[] {
			"Status",
			"FirsthMonth",
			"XXX1",
			"DiscountStep",
			"XXX"
        };

		interpretBlock();
	}
} public class TCDBStaticBlock extends InterpretedBlock {

	public ByteString mIdentifier;
	public RKFInteger mVersionNumber;
	public ByteString mAID;
	public RKFInteger mDiscountType1;
	public RKFInteger mDiscountType2;
	public RKFInteger mDiscountType3;
	public ByteString mFree;

	public TCDBStaticBlock(byte[] bits) {
		super("TCDBStatic", bits);

		mIdentifier = new ByteString(8, false);
		mVersionNumber = new RKFInteger(6, true);
		mAID = new ByteString(12, true);
		mDiscountType1 = new RKFInteger(8, true);
		mDiscountType2 = new RKFInteger(8, true);
		mDiscountType3 = new RKFInteger(8, true);
		mFree = new ByteString(78, true);

		mFields = new DataType[] {
			mIdentifier,
			mVersionNumber,
			mAID,
			mDiscountType1,
			mDiscountType2,
			mDiscountType3,
			mFree
		};
        mFieldNames = new String[] {
			"Identifier",
			"VersionNumber",
			"AID",
			"DiscountType1",
			"DiscountType2",
			"DiscountType3",
			"Free"
        };

		interpretBlock();
	}
} public class TCDI1Block extends InterpretedBlock {

	public ByteString mAIDPIX1;
	public ByteString mAIDPIX2;
	public ByteString mAIDPIX3;
	public ByteString mAIDPIX4;
	public ByteString mAIDPIX5;
	public ByteString mChecksum;

	public TCDI1Block(byte[] bits) {
		super("TCDI1", bits);

		mAIDPIX1 = new ByteString(24, true);
		mAIDPIX2 = new ByteString(24, true);
		mAIDPIX3 = new ByteString(24, true);
		mAIDPIX4 = new ByteString(24, true);
		mAIDPIX5 = new ByteString(24, true);
		mChecksum = new ByteString(8, true);

		mFields = new DataType[] {
			mAIDPIX1,
			mAIDPIX2,
			mAIDPIX3,
			mAIDPIX4,
			mAIDPIX5,
			mChecksum
		};
        mFieldNames = new String[] {
			"AIDPIX1",
			"AIDPIX2",
			"AIDPIX3",
			"AIDPIX4",
			"AIDPIX5",
			"Checksum"
        };

		interpretBlock();
	}
} public class TCDI2Block extends InterpretedBlock {

	public ByteString mAIDPIX6;
	public ByteString mAIDPIX7;
	public ByteString mAIDPIX8;
	public ByteString mAIDPIX9;
	public ByteString mAIDPIX10;
	public ByteString mChecksum;

	public TCDI2Block(byte[] bits) {
		super("TCDI2", bits);

		mAIDPIX6 = new ByteString(24, true);
		mAIDPIX7 = new ByteString(24, true);
		mAIDPIX8 = new ByteString(24, true);
		mAIDPIX9 = new ByteString(24, true);
		mAIDPIX10 = new ByteString(24, true);
		mChecksum = new ByteString(8, true);

		mFields = new DataType[] {
			mAIDPIX6,
			mAIDPIX7,
			mAIDPIX8,
			mAIDPIX9,
			mAIDPIX10,
			mChecksum
		};
        mFieldNames = new String[] {
			"AIDPIX6",
			"AIDPIX7",
			"AIDPIX8",
			"AIDPIX9",
			"AIDPIX10",
			"Checksum"
        };

		interpretBlock();
	}
} public class TCDI3Block extends InterpretedBlock {

	public ByteString mAIDPIX11;
	public ByteString mAIDPIX12;
	public ByteString mAIDPIX13;
	public ByteString mAIDPIX14;
	public ByteString mAIDPIX15;
	public ByteString mChecksum;

	public TCDI3Block(byte[] bits) {
		super("TCDI3", bits);

		mAIDPIX11 = new ByteString(24, true);
		mAIDPIX12 = new ByteString(24, true);
		mAIDPIX13 = new ByteString(24, true);
		mAIDPIX14 = new ByteString(24, true);
		mAIDPIX15 = new ByteString(24, true);
		mChecksum = new ByteString(8, true);

		mFields = new DataType[] {
			mAIDPIX11,
			mAIDPIX12,
			mAIDPIX13,
			mAIDPIX14,
			mAIDPIX15,
			mChecksum
		};
        mFieldNames = new String[] {
			"AIDPIX11",
			"AIDPIX12",
			"AIDPIX13",
			"AIDPIX14",
			"AIDPIX15",
			"Checksum"
        };

		interpretBlock();
	}
} public class TCPUDynamicv4Block extends InterpretedBlock {

	public RKFInteger mPurseTransactionNumber;
	public MoneyAmount24 mValue;
	public ByteString mXXX;
	public ByteString mMACAlgorithmIdentifier;
	public ByteString mMACKeyIdentifier;
	public ByteString mMACAuthenticator;

	public TCPUDynamicv4Block(byte[] bits) {
		super("TCPUDynamicv4", bits);

		mPurseTransactionNumber = new RKFInteger(16, true);
		mValue = new MoneyAmount24(24, true);
		mXXX = new ByteString(64, true);
		mMACAlgorithmIdentifier = new ByteString(2, true);
		mMACKeyIdentifier = new ByteString(6, true);
		mMACAuthenticator = new ByteString(16, true);

		mFields = new DataType[] {
			mPurseTransactionNumber,
			mValue,
			mXXX,
			mMACAlgorithmIdentifier,
			mMACKeyIdentifier,
			mMACAuthenticator
		};
        mFieldNames = new String[] {
			"PurseTransactionNumber",
			"Value",
			"XXX",
			"MACAlgorithmIdentifier",
			"MACKeyIdentifier",
			"MACAuthenticator"
        };

		interpretBlock();
	}
} public class TCPUDynamicv6Block extends InterpretedBlock {

	public RKFInteger mPurseTransactionNumber;
	public MoneyAmount24 mValue;
	public ByteString mXXX;

	public TCPUDynamicv6Block(byte[] bits) {
		super("TCPUDynamicv6", bits);

		mPurseTransactionNumber = new RKFInteger(16, true);
		mValue = new MoneyAmount24(24, true);
		mXXX = new ByteString(216, true);

		mFields = new DataType[] {
			mPurseTransactionNumber,
			mValue,
			mXXX
		};
        mFieldNames = new String[] {
			"PurseTransactionNumber",
			"Value",
			"XXX"
        };

		interpretBlock();
	}
} public class TCPUStaticBlock extends InterpretedBlock {

	public ByteString mIdentifier;
	public RKFInteger mVersionNumber;
	public ByteString mAID;
	public ByteString mPurseSerialNumber;
	public DateCompact mStartDate;
	public RKFInteger mDataPointer;
	public MoneyAmount24 mMinimumValue;
	public MoneyAmount24 mAutoLoadValue;
	public ByteString mUnused;

	public TCPUStaticBlock(byte[] bits) {
		super("TCPUStatic", bits);

		mIdentifier = new ByteString(8, false);
		mVersionNumber = new RKFInteger(6, true);
		mAID = new ByteString(12, true);
		mPurseSerialNumber = new ByteString(32, true);
		mStartDate = new DateCompact(14, true);
		mDataPointer = new RKFInteger(4, true);
		mMinimumValue = new MoneyAmount24(24, true);
		mAutoLoadValue = new MoneyAmount24(24, true);
		mUnused = new ByteString(4, true);

		mFields = new DataType[] {
			mIdentifier,
			mVersionNumber,
			mAID,
			mPurseSerialNumber,
			mStartDate,
			mDataPointer,
			mMinimumValue,
			mAutoLoadValue,
			mUnused
		};
        mFieldNames = new String[] {
			"Identifier",
			"VersionNumber",
			"AID",
			"PurseSerialNumber",
			"StartDate",
			"DataPointer",
			"MinimumValue",
			"AutoLoadValue",
			"Unused"
        };

		interpretBlock();
	}
} public class TCSTv4Block extends info.rejsekort.reader.rkf.TCSTBlock {

	public ByteString mIdentifier;
	public RKFInteger mVersionNumber;
	public ByteString mAID;
	public ByteString mPIX;
	public ByteString mStatus;
	public ByteString mXXX;

	public TCSTv4Block(byte[] bits) {
		super("TCSTv4", bits);

		mIdentifier = new ByteString(8, false);
		mVersionNumber = new RKFInteger(6, true);
		mAID = new ByteString(12, true);
		mPIX = new ByteString(12, true);
		mStatus = new ByteString(8, true);
		mXXX = new ByteString(138, true);
		mJourneyOriginDateTime = new DateTime(24, true);

		mFields = new DataType[] {
			mIdentifier,
			mVersionNumber,
			mAID,
			mPIX,
			mStatus,
			mXXX,
			mJourneyOriginDateTime
		};
        mFieldNames = new String[] {
			"Identifier",
			"VersionNumber",
			"AID",
			"PIX",
			"Status",
			"XXX",
			"JourneyOriginDateTime"
        };

		interpretBlock();
	}
} public class TCSTv5Block extends info.rejsekort.reader.rkf.TCSTBlock {

	public ByteString mIdentifier;
	public RKFInteger mVersionNumber;
	public ByteString mAID;
	public ByteString mPIX;
	public ByteString mStatus;
	public ByteString mXXX;
	public MoneyAmount24 mValue;
	public ByteString mXXX2;
	public RKFInteger mLocation;
	public ByteString mXXX3;

	public TCSTv5Block(byte[] bits) {
		super("TCSTv5", bits);

		mIdentifier = new ByteString(8, false);
		mVersionNumber = new RKFInteger(6, true);
		mAID = new ByteString(12, true);
		mPIX = new ByteString(12, true);
		mStatus = new ByteString(8, true);
		mXXX = new ByteString(47, true);
		mValue = new MoneyAmount24(24, true);
		mXXX2 = new ByteString(64, true);
		mLocation = new RKFInteger(14, true);
		mJourneyOriginDateTime = new DateTime(24, true);
		mXXX3 = new ByteString(76, true);

		mFields = new DataType[] {
			mIdentifier,
			mVersionNumber,
			mAID,
			mPIX,
			mStatus,
			mXXX,
			mValue,
			mXXX2,
			mLocation,
			mJourneyOriginDateTime,
			mXXX3
		};
        mFieldNames = new String[] {
			"Identifier",
			"VersionNumber",
			"AID",
			"PIX",
			"Status",
			"XXX",
			"Value",
			"XXX2",
			"Location",
			"JourneyOriginDateTime",
			"XXX3"
        };

		interpretBlock();
	}
} public abstract class DataType {
	/** The bits as a string of "0" and "1": "000110001..." */
	protected String mBits;
	protected boolean mReverse = true;
	public int mBitlength;
	
	public DataType(int bitlength, boolean reverse) {
		mReverse = reverse;
		mBitlength = bitlength;
	}
	
	public void fromBits(String bits) {
		mBits = bits;
		if (mReverse) {
			//reverse the bits
			mBits = new StringBuilder(bits).reverse().toString();
		}
		interpret();
	}
	
	abstract void interpret();
	
	public static byte[] hexStringToByteArray(String s) {
	    int len = s.length();
	    byte[] data = new byte[len / 2];
	    for (int i = 0; i < len; i += 2) {
	        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
	                             + Character.digit(s.charAt(i+1), 16));
	    }
	    return data;
	}
	
	public static String getHexString(byte[] buf) {
		StringBuffer sb = new StringBuffer();

		for (byte b : buf) {
			sb.append(String.format("%02x", b));
		}

		return sb.toString();
	}
	
	public static String getBinaryString(byte[] input){
	    StringBuilder sb = new StringBuilder();

	    for (byte c : input) {
	        for (int n =  128; n > 0; n >>= 1){
	            if ((c & n) == 0)
	                sb.append('0');
	            else sb.append('1');
	        }
	    }

	    return sb.toString();
	}
	
	public static byte[] binaryStringToByteArray(String s) {
		byte[] ret = new byte[(s.length()+8-1) / 8];

		BigInteger bigint = new BigInteger(s, 2);
		byte[] bigintbytes = bigint.toByteArray();
		
		if (bigintbytes.length > ret.length) {
			//get rid of preceding 0
			for (int i = 0; i < ret.length; i++) {
				ret[i] = bigintbytes[i+1];
			}
		}
		else {
			ret = bigintbytes;
		}
		return ret;
	}
}
import info.rejsekort.reader.rkf.blocks.CMIBlock;
import info.rejsekort.reader.rkf.blocks.CommonTCSTBlock;
import info.rejsekort.reader.rkf.blocks.InterpretedBlock;
import info.rejsekort.reader.rkf.blocks.TCAS1Block;
import info.rejsekort.reader.rkf.blocks.TCCIBlock;
import info.rejsekort.reader.rkf.blocks.TCCPStaticBlock;
import info.rejsekort.reader.rkf.blocks.TCDBDynamicBlock;
import info.rejsekort.reader.rkf.blocks.TCDBStaticBlock;
import info.rejsekort.reader.rkf.blocks.TCDI1Block;
import info.rejsekort.reader.rkf.blocks.TCDI2Block;
import info.rejsekort.reader.rkf.blocks.TCDI3Block;
import info.rejsekort.reader.rkf.blocks.TCPUDynamicv4Block;
import info.rejsekort.reader.rkf.blocks.TCPUDynamicv6Block;
import info.rejsekort.reader.rkf.blocks.TCPUStaticBlock;
import info.rejsekort.reader.rkf.blocks.TCSTv4Block;
import info.rejsekort.reader.rkf.blocks.TCSTv5Block;
import info.rejsekort.reader.rkf.datatypes.DataType;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import android.nfc.tech.MifareClassic;
import android.util.Log;
import android.widget.Toast;
package info.rejsekort.reader.rkf;




public class RKFCard {
	public static final String TAG = "RKFCard";

	MifareClassic mMFC;
	public CMIBlock mCMI;
	public TCCIBlock mTCCI;
	public TCDI1Block mTCDI1;
	public TCDI2Block mTCDI2;
	public TCDI3Block mTCDI3;
	public TCAS1Block mTCAS1;
	public TCPUStaticBlock mTCPUStatic;
	public InterpretedBlock mTCPUDynamic1;
	public InterpretedBlock mTCPUDynamic2;
	public ArrayList<TCELBlock_> mTCEL = new ArrayList<TCELBlock_>();
	public ArrayList<TCSTBlock> mTCST = new ArrayList<TCSTBlock>();
	public ArrayList<TCCPStaticBlock> mTCCP = new ArrayList<TCCPStaticBlock>();
	public TCDBStaticBlock mTCDBStatic;
	public ArrayList<TCDBDynamicBlock> mTCDBDynamic = new ArrayList<TCDBDynamicBlock>();

	
	public LinkedHashMap<String, InterpretedBlock> allBlocks = new LinkedHashMap<String, InterpretedBlock>();
	
	public static final byte[][] SECTORKEYS_A = {
		// sector 0
		DataType.hexStringToByteArray("fc00018778f7"),