package com.github.jthuraisamy.mastertap.models;
import android.content.Context;
import com.github.jthuraisamy.mastertap.Helper;
import com.github.jthuraisamy.mastertap.R;
import com.github.jthuraisamy.mastertap.TLVParser;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class Card {
private int id;
private String label;
private String pan;
private String expiryDate;
private String paymentDirectory;
private String aidFci;
private String magStripeData = "";
private Map<Integer, String> cvc3Map = new HashMap<Integer, String>();
private ArrayList<Integer> attemptedUNs = new ArrayList<Integer>();
public Card() {}
public Card(Context ctx) {
label = ctx.getResources().getString(R.string.default_label);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getPan() {
return pan;
}
public void setPan(String pan) {
this.pan = pan;
}
public String getExpiryDate() {
return expiryDate;
}
public void setExpiryDate(String expiryDate) {
this.expiryDate = expiryDate;
}
public String getPaymentDirectory() {
return paymentDirectory;
}
public void setPaymentDirectory(String paymentDirectory) {
this.paymentDirectory = paymentDirectory;
}
public String getAidFci() {
return aidFci;
}
public void setAidFci(String aidFci) {
this.aidFci = aidFci;
}
public String getMagStripeData() {
return magStripeData;
}
public void setMagStripeData(String magStripeData) {
this.magStripeData = magStripeData;
}
public Map<Integer, String> getCvc3Map() {
return cvc3Map;
}
public void setCvc3Map(Map<Integer, String> cvc3Map) {
this.cvc3Map = cvc3Map;
}
/**
* Return whether this Card has a computed CVC3 value for the given unpredictable number.
*
* @param unpredictableNumber int
* @return boolean
*/
public boolean hasUN(int unpredictableNumber) {
return cvc3Map.containsKey(unpredictableNumber);
}
public ArrayList<Integer> getAttemptedUNs() {
return attemptedUNs;
}
public void setAttemptedUNs(ArrayList<Integer> attemptedUNs) {
this.attemptedUNs = attemptedUNs;
}
/**
* Return the total possible number of unpredictable numbers.
*
* @return int
*/
public int getTotalUNs() {
int unpredictableNumberDigits = getUNDigits();
return (int) Math.pow(10, unpredictableNumberDigits);
}
/**
* Return the maximum number of digits an unpredictable number can have.
*
* @return int
*/
private int getUNDigits() {
byte[] magStripeData = Helper.hexToByte(this.magStripeData);
byte[] pUnAtcTrack1 = TLVParser.readTlv(magStripeData, new byte[]{(byte) 0x9F, 0x63});
byte[] nAtcTrack1 = TLVParser.readTlv(magStripeData, new byte[]{(byte) 0x9F, 0x64});
byte[] pUnAtcTrack2 = TLVParser.readTlv(magStripeData, new byte[]{(byte) 0x9F, 0x66});
byte[] nAtcTrack2 = TLVParser.readTlv(magStripeData, new byte[]{(byte) 0x9F, 0x67});
int kTrack1 = 0;
int tTrack1 = nAtcTrack1[0];
int kTrack2 = 0;
int tTrack2 = nAtcTrack2[0];
for (Byte b : pUnAtcTrack1) {
int i = (int) b;
if (i < 0) i += 256;
kTrack1 += Integer.bitCount(i);
}
for (Byte b : pUnAtcTrack2) {
int i = (int) b;
if (i < 0) i += 256;
kTrack2 += Integer.bitCount(i);
}
return Math.max(kTrack1 - tTrack1, kTrack2 - tTrack2);
}
@Override
public String toString() {
return String.format(
"Card [\n\t" +
"id = %d\n\t" +
"label = %s\n\t" +
"pan = %s\n\t" +
"expiry_date = %s\n\t" +
"payment_directory = %s\n\t" +
"aid_fci = %s\n\t" +
"magstripe_data = %s\n" +
"]",
id, label, pan, expiryDate, paymentDirectory, aidFci, magStripeData
);
}
}