package cn.net.cpzslibs.label;

import com.jymf.common.JYMD5;

import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class EchoLabelUtil {
	private static final byte[] keyBytes = { -85, -2, 54, -70, -85, 112, -70, 83, 49, 94, 92, 87, 53, 38, -77, 19 };

	private static final byte[][] G_B_KEY = {
			{ 27, -15, -66, -79, 16, -119, -85, 93, 63, 95, 79, -55, 49, 51, -77, 23 },
			{ -98, -25, -112, -61, 120, 89, -116, 25, 3, -29, -112, -75, 36, 85, -28, 97 },
			{ 106, 50, 8, -70, -81, 122, -29, 115, -89, -10, 14, -7, 67, -2, 8, -112 },
			new byte[] { -128, 88, 50, -92, -99, 11, -88, 80, -73, 9, -12, -95, 57, -84, 103, 1 },
			{ 76, -113, 46, -8, 10, -57, -58, 107, -58, 38, 125, -35, 37, -67, 37, 4 },
			{ 93, -58, -47, -43, -121, -86, -48, -57, 110, 57, -124, -28, -96, -24, 88, -62 },
			{ 63, -34, -59, -76, 51, 6, -15, -114, 122, 84, 55, -14, -87, -120, 116, -82 },
			{ -8, 47, 111, 43, -87, 83, -72, 76, 31, 5, 70, -40, -80, 119, -7, -81 },
			new byte[] { -22, 32, -1, 5, -67, 52, -96, -18, 36, -120, 33, 73, -58, 64, -52, 94 },
			{ -61, 27, -18, 16, 68, 127, -26, 15, 73, 104, 24, 87, -12, 32, 52, 79 } };

	public static String getCheckNum(String labelId) {
		int lableLength = labelId.length();
		for (int i = 0; i < 32 - lableLength; ++i)
			labelId = "0" + labelId;

		byte[] lableByte = new byte[16];
		lableByte = hexString2Bytes(labelId, false);
		try {
			byte[] key = getCheckCodeKey(labelId.substring(labelId.length() - lableLength));
			SecretKeySpec signingKey = new SecretKeySpec(key, "HmacSHA1");
			Mac mac = Mac.getInstance("HmacSHA1");
			mac.init(signingKey);
			byte[] rawHmac = mac.doFinal(lableByte);
			byte[] b = new byte[4];
			b[0] = rawHmac[(rawHmac.length - 4)];
			b[1] = rawHmac[(rawHmac.length - 3)];
			b[2] = rawHmac[(rawHmac.length - 2)];
			b[3] = rawHmac[(rawHmac.length - 1)];

			long intValue = -6520069580088410112L;
			for (int i = 0; i < b.length; ++i) {
				intValue += ((b[i] & 0xFF) << 8 * (3 - i));
			}
			String consNum = String.valueOf(intValue);
			labelId = labelId + consNum.substring(consNum.length() - 4);
			return labelId.substring(labelId.length() - lableLength + 4);
		} catch (Exception e) {
		}
		return "";
	}
	
	private static byte[] hexString2Bytes(String str, boolean isLowerCase) {
		byte[] b = new byte[str.length() / 2];
		for (int i = 0; i < b.length; ++i) {
			String s = str.substring(i * 2, i * 2 + 2);

			b[i] = hex2Byte(s, isLowerCase);
		}
		return b;
	}
	
	private static byte hex2Byte(String str, boolean isLowerCase) {
		String seed = getHexSeed(isLowerCase);
		return (byte) (seed.indexOf(str.substring(0, 1)) * 16 + seed.indexOf(str.substring(1, 2)));
	}
	
	private static String getHexSeed(boolean isLowerCase) {
		String seed = null;
		if (isLowerCase)
			seed = "0123456789abcdef";
		else
			seed = "0123456789ABCDEF";

		return seed;
	}
	
	private static byte[] getCheckCodeKey(String iLabelId)
			throws NoSuchAlgorithmException, UnsupportedEncodingException {
		if ((iLabelId.length() > "100051125618".length()) || (iLabelId.compareTo("100051125618") > 0)) {
			JYMD5 md5 = new JYMD5();
			String sSummary = md5.getMD5(iLabelId);
			int iSummary = 0;
			for (int i = 0; i < sSummary.length(); ++i) {
				char c = sSummary.charAt(i);
				int n = ((c & 0xF0) >> '\4') + ((c & 0xF) << '\4');
				iSummary += n;
			}
			return G_B_KEY[(iSummary % 10)];
		}
		return keyBytes;
	}
}
