package net.y3n20u.util;

public class ByteHelper {
	private static final String MESSAGE_DIFF_LENGTH = "cannot process because of the different length.";
	private static final String MESSAGE_NOT_EVEN = "the number of chars must be even (not odd).";

	/**
	 * get a byte array from hex string. white spaces (\\s) will be ignored.
	 * @param str source string. the length (except for white spaces) must an even number.
	 * @return
	 */
	public static byte[] getBytes(String str) {
		String spaceRemovedStr = str.replaceAll("\\s", "");
		int length = spaceRemovedStr.length() / 2;
		if (spaceRemovedStr.length() != length * 2) {
			throw new IllegalArgumentException(MESSAGE_NOT_EVEN);
		}
		byte[] r = new byte[length];
		String d;
		for (int i = 0; i < length; i++) {
			d = spaceRemovedStr.substring(i * 2, i * 2 + 2);
			r[i] = (byte)Integer.parseInt(d, 16);
		}
		return r;
	}

	public static String getHexString(byte ... data) {
		String r = "";
		for (byte d: data) {
			r += String.format("%1$02x", d & 0xff);
		}
		return r;
	}

	public static byte[] concatByteArrays(byte[] ... byteArrays) {
		int totalLength = 0;
		for (byte[] byteArray: byteArrays) {
			totalLength += byteArray.length;
		}
		return ByteHelper.concatByteArrays(totalLength, byteArrays);
	}

	public static byte[] concatByteArrays(int totalLength, byte[] ... byteArrays) {
		byte[] r = new byte[totalLength];
		int i = 0;
		for (byte[] byteArray: byteArrays) {
			for (byte b: byteArray) {
				r[i++] = b;
				if (i >= totalLength) {
					return r;
				}
			}
		}
		return r;
	}

	public static byte[] xorTwoByteArrays(byte[] formerByteArray, byte[] latterByteArray) {
		if (formerByteArray.length != latterByteArray.length) {
			throw new IllegalArgumentException(MESSAGE_DIFF_LENGTH);
		}
		byte[] r = new byte[formerByteArray.length];
		for (int i = 0; i < formerByteArray.length; i++) {
			r[i] = (byte) (formerByteArray[i] ^ latterByteArray[i]);
		}
		return r;
	}

	public static long getLong(byte ... bytes) {
		if (bytes.length > 8) {
			throw new IllegalArgumentException();
		}
		long r = 0;
		for (int i = 0; i < bytes.length; i++) {
			r |= (bytes[i] & 0xff) << (8 * i);
		}
		return r;
	}

	public static int getInt(byte ... bytes) {
		if (bytes.length > 4) {
			throw new IllegalArgumentException();
		}
		int r = 0;
		for (int i = 0; i < bytes.length; i++) {
			r |= (bytes[i] & 0xff) << (8 * i);
		}
		return r;
	}
}
