package com.iwunu.iot.common.util;

import java.io.UnsupportedEncodingException;
import java.util.Random;

/**
 * Status		: 
 * Created By	: Ben Lin at 2015-09-28
 * Description	:
 */

public class ByteTools {

	// Return a string of the given byte in format: 
	//0x02
	public static String byteToString( byte b ) {
		int tmp = b & 0xff;
		if( tmp < 16 ) return "0x0" + Integer.toHexString(tmp);
		else return "0x" + Integer.toHexString(tmp);
	}
	
	// Return a string of the given bytes in format: 
		// 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
		// 0x08, 0x09, 0x0a
		public static String bytesToStringOx( byte[] bytes ) {
			
			if( bytes == null || bytes.length == 0 ) return "";
			
			StringBuilder str = new StringBuilder(bytes.length*2+10);
			for(int i=0; i<bytes.length; i++) {
				int tmp = bytes[i] & 0xff;
				if( i != 0 ) str.append(" \t");
				if( i % 8 == 0 ) str.append("\n");
				if( tmp < 16 ) str.append("0x0");
				else str.append("0x");
				str.append(Integer.toHexString(tmp));
			}
			return str.toString();
		}
		public static String bytesToString( byte[] bytes ) {
			
			if( bytes == null || bytes.length == 0 ) return "";
			
			StringBuilder str = new StringBuilder(bytes.length*2+10);
			for(int i=0; i<bytes.length; i++) {
				int tmp = bytes[i] & 0xff;
				if( tmp < 16 ) str.append("0");
				str.append(Integer.toHexString(tmp));
			}
			return str.toString();
		}
	// Convert bytes to hex string
	// Bytes: {0x41, 0x42, 0x43, 0x44, 0x45, 0x46}
	// HexString: "414243444546"
	public static String bytesToHexString(byte[] bytes) {
		
	    if( bytes == null || bytes.length == 0 ) return null;
	    
		StringBuilder builder = new StringBuilder(bytes.length*2+10);
		for(int i=0; i<bytes.length; i++) {
			int tmp = bytes[i] & 0xff;
			if( tmp < 16 ) builder.append("0");
			builder.append(Integer.toHexString(tmp));
		}
		return builder.toString();
	}

	public static String bytesToHexString(byte[] bytes, int start, int length) {
		
	    if( bytes == null || bytes.length == 0 ) return null;
	    if( start < 0 || start >= bytes.length ) return null;
	    if( length <= 0 ) return null;
	    if( start + length > bytes.length ) length = bytes.length - start;
	    
	    byte[] newBytes = new byte[length];
	    System.arraycopy(bytes, start, newBytes, 0, length);
	    
		StringBuilder builder = new StringBuilder(newBytes.length*2+10);
		for(int i=0; i<newBytes.length; i++) {
			int tmp = newBytes[i] & 0xff;
			if( tmp < 16 ) builder.append("0");
			builder.append(Integer.toHexString(tmp));
		}
		return builder.toString();
	}
	
	//Convert char to byte
	public static byte charToByte(char c) {
		return (byte) "0123456789ABCDEF".indexOf(c);  
	}
	 
	// Convert hex string to byte[]
	// hex string: 010203040506
	// byte[]" {0x01, 0x02, 0x03, 0x04, 0x05, 0x06}
	public static byte[] hexStringToBytes(String hexString) {
		
	    if( hexString == null || hexString.equals("") ) return null;

	    hexString = hexString.toUpperCase();  
	    int length = hexString.length() / 2;  
	    char[] hexChars = hexString.toCharArray();
	    
	    byte[] d = new byte[length];  
	    for (int i = 0; i < length; i++) {  
	        int pos = i * 2;
	        d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));  
	    }
	    return d;  
	}

	
	// Convert string bytes to byte string
	// stringBytes: {0x41, 0x42, 0x43, 0x44, 0x45, 0x46}
	// Bytestring: "ABCDEF"
	public static String stringBytesToByteString(byte[] stringBytes) {
		
	    if( stringBytes == null || stringBytes.length == 0 ) return null;
	    
		StringBuilder builder = new StringBuilder(stringBytes.length*2);
		for(int i=0; i<stringBytes.length; i++) {
			char temp = (char)stringBytes[i];
			if( temp == '\0' ) break;
			builder.append(temp);
		}
		return builder.toString();
	}

	// Convert string bytes to byte[]
	// stringBytes: {0x41, 0x42, 0x43, 0x44, 0x45, 0x46}
	// byte[]" {0xAB, 0xCD, 0xEF}
	public static byte[] stringBytesToBytes(byte[] stringBytes) {
		
	    if( stringBytes == null || stringBytes.length == 0 ) return null;

	    int length = stringBytes.length / 2;
	    
	    byte[] bytes = new byte[length];
	    for (int i = 0; i < length; i++) {
	        int pos = i * 2;	        
	        byte byte1 = stringBytes[pos];
	        byte byte2 = stringBytes[pos+1];
	        if( byte1 >= 97 ) byte1 -= 32;
	        if( byte2 >= 97 ) byte2 -= 32;	        
	        bytes[i] = (byte) (charToByte((char)byte1) << 4 | charToByte((char)byte2));  
	    }
	    return bytes;  
	}
	
	public static byte int2OneByte(int num) {
		return (byte) (num & 0x000000ff);
	}

	// Transform the received key from key chars to bytes.
	public static byte[] revertBytes( byte[] bytes ) {

		if( bytes == null || bytes.length == 0 ) return bytes;

		byte[] newBytes = new byte[bytes.length];		
		for(int i=0; i<bytes.length; i++) {
			newBytes[bytes.length-1-i] = bytes[i];
		}
		
		return newBytes;
	}
	
	public static byte[] revertBytesForWord( byte[] bytes ) {

		if( bytes == null || bytes.length == 0 ) return bytes;

		byte[] newBytes = new byte[bytes.length];
		for(int i=0; i*8<bytes.length; i++) {
			newBytes[i*8+7] = bytes[i*8+6];
			newBytes[i*8+6] = bytes[i*8+7];
			newBytes[i*8+5] = bytes[i*8+4];
			newBytes[i*8+4] = bytes[i*8+5];
			newBytes[i*8+3] = bytes[i*8+2];
			newBytes[i*8+2] = bytes[i*8+3];
			newBytes[i*8+1] = bytes[i*8+0];
			newBytes[i*8+0] = bytes[i*8+1];
		}
		
		return newBytes;
	}
	

	public static byte[] revertByte( byte[] bytes ) {

		if( bytes == null || bytes.length == 0 ) return bytes;

		byte[] newBytes = new byte[bytes.length];
		for(int i=0; i*2<bytes.length; i++) {
			newBytes[i*2] = bytes[i*2+1];
			newBytes[i*2+1] = bytes[i*2];
		}
		
		return newBytes;
	}
	
	public static byte[] stringToByteArray( String str ) {
		if( str == null || str.length() <= 0 ) return null;

		byte[] bytes = new byte[str.length()];
		for( int i=0; i<str.length(); i++ ) bytes[i] = (byte)str.charAt(i);
		/*
		char[] chars = str.toCharArray();
		byte[] bytes = new byte[chars.length];
		for(int i=0; i<chars.length; i++) bytes[i] = (byte)chars[i];
		*/
		return bytes;
	}
	
	public static byte[] generateRandomBytes(int length) {
		
		if( length <= 0 ) return null;

		byte[] bytes = new byte[length];
		Random random = new Random();
		random.nextBytes(bytes);
		
		return bytes;
	}
	
	// byte 数组与 int 的相互转换  
	public static int bytesToInt(byte[] b) {
		
		int sign = b[0] & 0x80;
		byte[] tmpBytes = new byte[4];
		for( int i=0; i<4; i++ ) {
			
			if( i < b.length ) {

				tmpBytes[3-i] = b[b.length-1-i];
				
			} else {

				if( sign == 0 ) tmpBytes[3-i] = 0x00;
				else tmpBytes[3-i] = (byte)0xFF;
			}
		}
			
		int result = 0;
		for( int i=0; i<4; i++) result = (result << 8) | (tmpBytes[i] & 0xFF);
		return result;
	}  
	  
	public static byte[] intToBytes(int a, int arrayLength) {
		
		byte[] result = new byte[arrayLength];
		int tmp = a;
		for( int i=arrayLength-1; i>= 0; i-- ) {
			result[i] = (byte) (tmp & 0xFF);
			tmp = tmp >> 8;
		}

		return result;
	} 

	public static long bytesToLong(byte[] b) {

		long result = 0;
		for( int i=0; i<b.length && i<8; i++) result = (result << 8) | (b[i] & 0xFF);
	    return result;  
	 }
	
	public static byte[] longToBytes(long values, int arrayLength) {

		byte[] result = new byte[arrayLength];
		long tmp = values;
		for( int i=arrayLength-1; i >= 0; i-- ) {
			result[i] = (byte) (tmp & 0xFF);
			tmp = tmp >> 8;
		}

		return result;  
	}

	public static int byteToInt(byte b) {

		int temp = b;
		temp = temp & 0x000000FF;
		return temp;
	}
	
	public static String bytesToIPString(byte[] ipBytes) {
		
		if( ipBytes == null ) return null;
			
		StringBuilder builder = new StringBuilder();
		for( int i=0; i<ipBytes.length; i++ ) {
			
			if( i != 0 ) builder.append(".");
			
			builder.append(ByteTools.byteToInt(ipBytes[i]));
		}
		
		return builder.toString();
	}
	/**
	 * 16进制转换成为string类型字符串
	 * @param s
	 * @return
	 */
	public static String hexStringToString(String s) {
	    if (s == null || s.equals("")) {
	        return null;
	    }
	    s = s.replace(" ", "");
	    byte[] baKeyword = new byte[s.length() / 2];
	    for (int i = 0; i < baKeyword.length; i++) {
	        try {
	            baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16));
	        } catch (Exception e) {
	            e.printStackTrace();
	        }
	    }
	    try {
	        s = new String(baKeyword, "UTF-8");
	        new String();
	    } catch (Exception e1) {
	        e1.printStackTrace();
	    }
	    return s;
	}
	 public static int hexToUint(String pm){
			int ten = Integer.parseInt(pm, 16);
			byte value = (byte) ten;//解决二进制补码
			String ss = String.valueOf(value);
			return  Integer.parseInt(ss);
	 }
	
	public static float bytesToFloat(byte[] b) {
		byte[] reverted = ByteTools.revertBytes(b);
        return Float.intBitsToFloat(ByteTools.bytesToInt(reverted));
    }
	/**
	* @Title:bytes2HexString
	* @Description:字节数组转16进制字符串
	* @param b
	* 字节数组
	* @return 16进制字符串
	* @throws
	*/
	public static String bytes2HexString(byte[] b) {
		StringBuffer result = new StringBuffer();
		for (int i = 0; i < b.length; i++) {
			result.append(String.format("%02X",b[i]));
		}
		return result.toString();
	}
	/**
	* @Title:hexString2Bytes
	* @Description:16进制字符串转字节数组
	* @param src
	* 16进制字符串
	* @return 字节数组
	* @throws
	*/
	public static byte[] hexString2Bytes(String src) {
		int l = src.length() / 2;
		byte[] ret = new byte[l];
		for (int i = 0; i < l; i++) {
			ret[i] = Integer.valueOf(src.substring(i * 2, i * 2 + 2), 16).byteValue();
		}
		return ret;
	}
	/**
	* @Title:string2HexString
	* @Description:字符串转16进制字符串
	* @param strPart 字符串
	* @param tochartype hex目标编码
	* @return 16进制字符串
	* @throws
	*/
	public static String string2HexString(String strPart,String tochartype) {
		try{
			return bytes2HexString(strPart.getBytes(tochartype));
			}catch (Exception e){
			return "";
		}
	}
    /**
    * @Title:string2HexGBK
    * @Description:字符GBK串转16进制字符串
    * @param strPart
    * 字符串
    * @return 16进制字符串
    * @throws
    */
    public static String string2HexGBK(String strPart) {
    	return string2HexString(strPart,"GBK");
    }
	public static void main(String[] args) throws UnsupportedEncodingException {
		System.out.println(string2HexGBK("你好吗"));
		
//		System.out.println(ByteTools.bytesToFloat(ByteTools.hexStringToBytes("10977942")));
//		System.out.println(ByteTools.bytesToFloat(ByteTools.hexStringToBytes("41447080")));
//		System.out.println(ByteTools.bytesToFloat(ByteTools.hexStringToBytes("42799710")));
//		System.out.println(ByteTools.hexStringToBytes("16a17db5a76ef914015358bbd669ebcd014b40b4504d13735a0bf32d05b84dac6a1a04a5a028a04a28128a0a745014a6681c548ea2928128a07a5a05a2816928168a072d2d029fd2801c879ad0b57a0b17237a5634ab86a0653a80168a072f5adb67a05bc8f23359a681b4ea029280a2801292802a5140549136d341a4b7b148b891529b4b69bfd5beda0af2e9d2afddf987b555789d3ef29a0653a80168a028a05a4a07a7503ba536801455bb77e68034c1dc959778986a0ab4b40b4b40a2ad4f8a0d0fbf1d64dc2ec7a088514052501450251401528a028a05a7ac84505986fa44ef56c6a0927fad40681df66b4b8fb8db0d44fa5bff07cd4151ede44eaa6a3db40525014b40a29dd281334502d4b1360d069dbbd47789914019add69a281f4b40ea7a1a0d2b57c8a83508bf8a833e9280a280a4a028a0a9450145014502d140f12115622bd9233f7a802f26a9bb895430a7e2d27ff64d0324d2fbc4e1aa9c9692c7d54d04568a07f414d3405140b4e5eb40176ddeadc9f325065ceb86a86801c29f40b4b416ad9f157a45f322a0c79936362a3a029280a280128a0ab45"));
	}
}
