package com.betomaluje.miband.model;
import android.content.Context;
import android.content.SharedPreferences;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.Random;
public class UserInfo {
public static final String KEY_PREFERENCES = "user_info_preferences";
public static final String KEY_BT_ADDRESS = "bt_address";
public static final String KEY_GENDER = "gender";
public static final String KEY_AGE = "age";
public static final String KEY_HEIGHT = "height";
public static final String KEY_WEIGHT = "weight";
public static final String KEY_ALIAS = "alias";
public static final String KEY_TYPE = "type";
private String btAddress;
private int uid;
private byte gender;
private byte age;
private byte height; // cm
private byte weight; // kg
private String alias = "";
private byte type;
private byte[] data = new byte[20];
private UserInfo() {
}
public UserInfo(String btAdress, int gender, int age, int height, int weight, String alias, int type) {
this.btAddress = btAdress;
this.gender = (byte) gender;
this.age = (byte) age;
this.height = (byte) (height & 0xFF);
this.weight = (byte) weight;
this.alias = alias;
this.uid = calculateUidFrom(alias);
this.type = (byte) type;
byte[] sequence = new byte[20];
int uid = calculateUidFrom(alias);
String normalizedAlias = ensureTenCharacters(alias);
sequence[0] = (byte) uid;
sequence[1] = (byte) (uid >>> 8);
sequence[2] = (byte) (uid >>> 16);
sequence[3] = (byte) (uid >>> 24);
sequence[4] = (byte) (gender & 0xff);
sequence[5] = (byte) (age & 0xff);
sequence[6] = (byte) (height & 0xff);
sequence[7] = (byte) (weight & 0xff);
sequence[8] = (byte) (type & 0xff);
for (int u = 9; u < 19; u++)
sequence[u] = normalizedAlias.getBytes()[u - 9];
byte[] crcSequence = new byte[19];
System.arraycopy(sequence, 0, crcSequence, 0, crcSequence.length);
sequence[19] = (byte) ((getCRC8(crcSequence) ^ Integer.parseInt(btAdress.substring(btAdress.length() - 2), 16)) & 0xff);
this.data = sequence;
}
public static UserInfo create(String address, int gender, int age, int height, int weight, String alias, int type) throws IllegalArgumentException {
if (address == null || address.length() == 0) {
throw new IllegalArgumentException("Invalid parameters");
}
try {
return new UserInfo(address, gender, age, height, weight, alias, type);
} catch (Exception ex) {
throw new IllegalArgumentException("Illegal user info data", ex);
}
}
/**
* Creates a default user info.
*
* @param btAddress the address of the MI Band to connect to.
*/
public static UserInfo getDefault(String btAddress, Context context) {
try {
return getSavedUser(context);
} catch (IllegalArgumentException e) {
return new UserInfo(btAddress, 0, 26, 180, 80, "1550050550", 0);
}
}
private String ensureTenCharacters(String alias) {
char[] result = new char[10];
//int aliasLen = alias.length();
int maxLen = Math.min(10, alias.length());
int diff = 10 - maxLen;
for (int i = 0; i < maxLen; i++) {
result[i + diff] = alias.charAt(i);
}
for (int i = 0; i < diff; i++) {
result[i] = '0';
}
return new String(result);
}
private int calculateUidFrom(String alias) {
int uid = 0;
try {
uid = Integer.parseInt(alias);
} catch (NumberFormatException ex) {
uid = alias.hashCode(); // simple as that
}
return uid;
}
public static UserInfo fromByteData(byte[] data) {
if (data.length < 9) {
return null;
}
UserInfo info = new UserInfo();
info.uid = data[3] << 24 | (data[2] & 0xFF) << 16 | (data[1] & 0xFF) << 8 | (data[0] & 0xFF);
info.gender = data[4];
info.age = data[5];
info.height = data[6];
info.weight = data[7];
try {
info.alias = data.length == 9 ? "" : new String(data, 8, data.length - 9, "UTF-8");
} catch (UnsupportedEncodingException e) {
info.alias = "";
}
info.type = data[data.length - 1];
return info;
}
public byte[] getBytes(String mBTAddress) {
byte[] aliasBytes;
try {
aliasBytes = this.alias.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
aliasBytes = new byte[0];
}
ByteBuffer bf = ByteBuffer.allocate(20);
bf.put((byte) (uid & 0xff));
bf.put((byte) (uid >> 8 & 0xff));
bf.put((byte) (uid >> 16 & 0xff));
bf.put((byte) (uid >> 24 & 0xff));
bf.put(this.gender);
bf.put(this.age);
bf.put(this.height);
bf.put(this.weight);
bf.put(this.type);
if (aliasBytes.length <= 10) {
bf.put(aliasBytes);
bf.put(new byte[10 - aliasBytes.length]);
} else {
bf.put(aliasBytes, 0, 10);
}
byte[] crcSequence = new byte[19];
for (int u = 0; u < crcSequence.length; u++)
crcSequence[u] = bf.array()[u];
byte crcb = (byte) ((getCRC8(crcSequence) ^ Integer.parseInt(mBTAddress.substring(mBTAddress.length() - 2), 16)) & 0xff);
bf.put(crcb);
return bf.array();
}
private int getCRC8(byte[] seq) {
int len = seq.length;
int i = 0;
byte crc = 0x00;
while (len-- > 0) {
byte extract = seq[i++];
for (byte tempI = 8; tempI != 0; tempI--) {
byte sum = (byte) ((crc & 0xff) ^ (extract & 0xff));
sum = (byte) ((sum & 0xff) & 0x01);
crc = (byte) ((crc & 0xff) >>> 1);
if (sum != 0) {
crc = (byte) ((crc & 0xff) ^ 0x8c);
}
extract = (byte) ((extract & 0xff) >>> 1);
}
}
return (crc & 0xff);
}
public String toString() {
return "uid:" + this.uid
+ ",gender:" + this.gender
+ ",age:" + this.age
+ ",height:" + this.getHeight()
+ ",weight:" + this.getWeight()
+ ",alias:" + this.alias
+ ",type:" + this.type;
}
/**
* @return the uid
*/
public int getUid() {
return uid;
}
/**
* @return the gender
*/
public byte getGender() {
return gender;
}
/**
* @return the age
*/
public byte getAge() {
return age;
}
/**
* @return the height
*/
public int getHeight() {
return (height & 0xFF);
}
/**
* @return the weight
*/
public int getWeight() {
return weight & 0xFF;
}
/**
* @return the alias
*/
public String getAlias() {
return alias;
}
/**
* @return the type
*/
public byte getType() {
return type;
}
public byte[] getData() {
return this.data;
}
public static UserInfo getSavedUser(Context context) {
SharedPreferences sharedPrefs = context.getSharedPreferences(KEY_PREFERENCES, Context.MODE_PRIVATE);
String btAddress = sharedPrefs.getString(KEY_BT_ADDRESS, "");
int gender = sharedPrefs.getInt(KEY_GENDER, -1);
int age = sharedPrefs.getInt(KEY_AGE, -1);
int height = sharedPrefs.getInt(KEY_HEIGHT, -1);
int weight = sharedPrefs.getInt(KEY_WEIGHT, -1);
String alias = sharedPrefs.getString(KEY_ALIAS, "");
int type = sharedPrefs.getInt(KEY_TYPE, -1);
//String TAG = "UserInfo";
//Log.e(TAG, "address: " + btAddress);
//Log.e(TAG, "gender: " + gender);
//Log.e(TAG, "age: " + age);
//Log.e(TAG, "height: : " + height);
//Log.e(TAG, "weight: " + weight);
//Log.e(TAG, "alias: " + alias);
return create(btAddress, gender, age, height, weight, alias, type);
}
public static String generateAlias() {
char[] chars = "0123456789".toCharArray();
StringBuilder sb = new StringBuilder();
Random random = new Random();
for (int i = 0; i < 10; i++) {
char c = chars[random.nextInt(chars.length)];
sb.append(c);
}
return sb.toString();
}
}