package com.jiayue.ipfcst.fileupload.util;


import com.sun.istack.internal.NotNull;
import io.netty.buffer.ByteBuf;

import javax.xml.bind.DatatypeConverter;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Formatter;

/**
 * 字节转换工具类
 *
 * @author xsl
 * @version 3.0
 */
public abstract class ByteUtil {

  /**
   * int类型转换byte[4]数组，数组内字节由高到低
   *
   * @param n 被转换int
   * @return byte[4]
   */
  public static byte[] intToBytesFromHighToLow(@NotNull int n) {
    byte[] result = new byte[4];
    result[0] = (byte) ((n >> 24) & 0xFF);
    result[1] = (byte) ((n >> 16) & 0xFF);
    result[2] = (byte) ((n >> 8) & 0xFF);
    result[3] = (byte) (n & 0xFF);
    return result;
  }

  /**
   * byte[4]数组类型转换int，数组内字节由高到低
   *
   * @param b 被转换的字节数组
   * @return int
   */
  public static int bytesToIntFromHighToLow(@NotNull byte[] b) {

    return (b[(0)] & 0xFF) << 24 | (b[(1)] & 0xFF) << 16 |
      (b[(2)] & 0xFF) << 8 | b[3] & 0xFF;
  }


  /**
   * int类型转换byte[4]数组，数组内字节由低到高
   *
   * @param n 被转换int
   * @return byte[4]
   */
  public static byte[] intToBytesFromLowToHigh(@NotNull int n) {
    byte[] targets = new byte[4];

    targets[0] = ((byte) (n & 0xFF));
    targets[1] = ((byte) (n >> 8 & 0xFF));
    targets[2] = ((byte) (n >> 16 & 0xFF));
    targets[3] = ((byte) (n >> 24 & 0xFF));
    return targets;
  }

  /**
   * byte[4]数组类型转换int，数组内字节由低到高
   *
   * @param b 被转换的字节数组
   * @return int
   */
  public static int bytesToIntFromLowToHigh(@NotNull byte[] b) {
    return (b[(3)] & 0xFF) << 24 | (b[(2)] & 0xFF) << 16 |
      (b[(1)] & 0xFF) << 8 | b[0] & 0xFF;
  }

  /**
   * 二进制转十六进制，数组内字节由高到低
   *
   * @param b 二进制数组
   * @return 十六进制字符串
   */
  public static String bytesToHexStringFromHighToLow(@NotNull byte[] b) {
    return DatatypeConverter.printHexBinary(b);
  }

  /**
   * 十六进制转二进制，数组内字节由高到低
   *
   * @param hexString 十六进制字符串
   * @return 二进制数组
   */
  public static byte[] hexStringToBytesFromHighToLow(@NotNull String hexString) {
    return DatatypeConverter.parseHexBinary(hexString);
  }

  /**
   * 二进制转十六进制，数组内字节由低到高
   *
   * @param b 二进制数组
   * @return 十六进制字符串
   */
  public static String bytesToHexStringFromLowToHigh(@NotNull byte[] b) {

    byte[] dest = ByteUtil.bytesFlipping(b);
    return DatatypeConverter.printHexBinary(dest);
  }

  /**
   * 十六进制转二进制，数组内字节由低到高
   *
   * @param hexString 十六进制字符串
   * @return 二进制数组
   */
  public static byte[] hexStringToBytesFromLowToHigh(@NotNull String hexString) {
    byte[] dest = DatatypeConverter.parseHexBinary(hexString);
    return ByteUtil.bytesFlipping(dest);
  }

  /**
   * float转换byte[4]数组，数组内字节由低到高
   *
   * @param f 被转换float
   * @return byte[4]
   */
  public static byte[] floatToBytesFromLowToHigh(@NotNull float f) {
    int fbit = Float.floatToIntBits(f);

    byte[] b = new byte[4];
    for (int i = 0; i < 4; i++) {
      b[i] = ((byte) (fbit >> 24 - i * 8));
    }
    // 翻转数组
    return ByteUtil.bytesFlipping(b);
  }

  /**
   * byte[4]数组转换float，数组内字节由低到高
   *
   * @param b 被转换字节数组
   * @return float
   */
  public static float bytesToFloatFromLowToHigh(@NotNull byte[] b) {
    int l = b[(0)];
    l &= 255;
    l = l | b[(1)] << 8;
    l &= 65535;
    l = l | b[(2)] << 16;
    l &= 16777215;
    l = l | b[(3)] << 24;
    return Float.intBitsToFloat(l);
  }

  /**
   * float转换byte[4]数组，数组内字节由高到低
   *
   * @param f 被转换float
   * @return byte[4]
   */
  public static byte[] floatToBytesFromHighToLow(@NotNull float f) {
    int fbit = Float.floatToIntBits(f);

    byte[] b = new byte[4];
    for (int i = 0; i < 4; i++) {
      b[i] = ((byte) (fbit >> 24 - i * 8));
    }
    return b;
  }

  /**
   * byte[4]数组转换float，数组内字节由高到低
   *
   * @param b 被转换字节数组
   * @return float
   */
  public static float bytesToFloatFromHighToLow(@NotNull byte[] b) {
    byte[] dest = ByteUtil.bytesFlipping(b);
    return ByteUtil.bytesToFloatFromLowToHigh(dest);
  }

  /**
   * 数组翻转
   *
   * @param res 原数组
   * @return 翻转后的数组
   */
  public static byte[] bytesFlipping(@NotNull byte[] res) {
    // 翻转数组
    int len = res.length;
    // 建立一个与源数组元素类型相同的数组
    byte[] dest = new byte[len];
    // 为了防止修改源数组，将源数组拷贝一份副本
    System.arraycopy(res, 0, dest, 0, len);
    // 将顺位第i个与倒数第i个交换
    for (int i = 0; i < len / 2; i++) {
      byte temp = dest[i];
      dest[i] = dest[(len - i - 1)];
      dest[(len - i - 1)] = temp;
    }
    return dest;
  }

  /**
   * 强制转换字符串为字节数组
   *
   * @param s 字符串
   * @return 字节数组
   */
  public static byte[] parseByte(String s) {
    char[] c = s.toCharArray();
    byte[] b = new byte[c.length];
    for (int i = 0; i < c.length; i++) {
      b[i] = Byte.parseByte(String.valueOf(c[i]));
    }
    return b;
  }

  /**
   * 16进制转10进制
   *
   * @param hex 字符串
   * @return int
   */
  public static int hexToDec(String hex) {
    BigInteger bigint = new BigInteger(hex, 16);
    return bigint.intValue();
  }

  /**
   * 10进制转16进制字符串低位在前高位在后
   *
   * @param dec
   * @return
   */
  public static String decToHex(int dec) {
    int var1 = 1;
    int var2 = dec >> 8;
    int var3 = dec & 255;
    String var4 = Integer.toHexString(var2);
    String var5 = Integer.toHexString(var3);
    if(var4.length() > 2) {
      do {
        if(var1 > 1) {
          var2 >>= 8;
        }
        var4 = Integer.toHexString(var2 >> 8);
        var5 = var5 + Integer.toHexString(var2 & 255);
        ++var1;
      } while(var4.length() > 2);
    }
    if(var4.length() < 2) {
      var4 = "0" + var4;
    }
    if(var5.length() < 2) {
      var5 = "0" + var5;
    }
    return var5 + var4;
  }

  /**
   * 把byte[]数组转换成十六进制字符串表示形式
   *
   * @param tmp 要转换的byte[]
   * @return 十六进制字符串表示形式
   */
  public static String byteToHexString(byte[] tmp) {
    char hexdigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    String s;
    // 用字节表示就是 16 个字节
    char str[] = new char[16 * 2]; // 每个字节用 16 进制表示的话，使用两个字符，
    // 所以表示成 16 进制需要 32 个字符
    int k = 0; // 表示转换结果中对应的字符位置
    for (int i = 0; i < 16; i++) { // 从第一个字节开始，对 MD5 的每一个字节
      // 转换成 16 进制字符的转换
      byte byte0 = tmp[i]; // 取第 i 个字节
      str[k++] = hexdigits[byte0 >>> 4 & 0xf]; // 取字节中高 4 位的数字转换,
      // >>> 为逻辑右移，将符号位一起右移
      str[k++] = hexdigits[byte0 & 0xf]; // 取字节中低 4 位的数字转换
    }
    s = new String(str); // 换后的结果转换为字符串
    return s;
  }

  /**
   * 16进制的字符串表示转成字节数组
   *
   * @param hexString
   *            16进制格式的字符串
   * @return 转换后的字节数组
   **/
  public static byte[] toByteArray(String hexString) {
    final byte[] byteArray = new byte[hexString.length() / 2];
    int k = 0;
    for (int i = 0; i < byteArray.length; i++) {//因为是16进制，最多只会占用4位，转换成字节需要两个16进制的字符，高位在先
      byte high = (byte) (Character.digit(hexString.charAt(k), 16) & 0xff);
      byte low = (byte) (Character.digit(hexString.charAt(k + 1), 16) & 0xff);
      byteArray[i] = (byte) (high << 4 | low);
      k += 2;
    }
    return byteArray;
  }

  /**
   * 字节数字转16进制字符串
   *
   * @param ba ba
   * @return string
   */
  public static String Byte2String(byte[] ba){
    if(ba == null || ba.length == 0)
    { return null;}
    Formatter f = new Formatter();
    String resultStr;
    try {
      for (int i = 0; i < ba.length; ++i) {
        f.format("%02x ", ba[i]);
      }
      resultStr = f.toString();
    }
    finally {
      f.close();
    }
    return resultStr;
  }

  /**
   * 字节数缓冲区字转16进制字符串
   *
   * @param buf buf
   * @return string
   */
  public static String ByteBuf2String(ByteBuf buf){
    if(!buf.isReadable()){
      return null;
    }
    ByteBuf b1=buf.copy();
    byte []bs=new byte[b1.readableBytes()];
    b1.readBytes(bs);
    b1.release();
    return Byte2String(bs);
  }

  public static void main(String[] args) {
    byte[] a = {89, 89, 71, 68, 52, 51, 95, 50, 48, 50, 49, 49, 48, 49, 56, 95, 49, 48, 49, 48, 95, 81, 88, 90, 46, 80, 86, 68};
    String c= Byte2String(a);
    System.out.println(c);
//    byte[] b = {73,2};
//    byte[] c = bytesFlipping(b);
//    String info = DatatypeConverter.printHexBinary(c);
//    BigInteger bigint=new BigInteger(info, 16);
//    int numb=bigint.intValue();
//    System.out.println(numb);

//    String[] returnMessage = {"10", "ctrl", "FF", "FF", "crc", "16"};

//    Long a=1589130920L;
//    ByteArrayOutputStream baos = new ByteArrayOutputStream();
//    DataOutputStream dos = new DataOutputStream(baos);
//    try {
//      dos.writeLong(a);
//    } catch (IOException e) {
//      e.printStackTrace();
//    }
////再读出来
//    byte[] buf = baos.toByteArray();
//    System.out.println(bytesToHexStringFromHighToLow(intToBytesFromLowToHigh(bytesToIntFromHighToLow(buf))));
//
//
//    System.out.println(bytesToHexStringFromHighToLow(floatToBytesFromLowToHigh(a.floatValue())));
//
//    System.out.println(bytesToHexStringFromHighToLow(intToBytesFromLowToHigh(a.intValue())));
//
//
//
//    System.out.println(bytesToHexStringFromHighToLow(intToBytesFromLowToHigh(hexToDec(Long.toHexString(a)))));

//    System.out.println(bytesToIntFromLowToHigh(hexStringToBytesFromLowToHigh(Long.toHexString(a))));
// A8 36 B8 5E
//    byte[] b = {(byte)0x3c,(byte)0x00,(byte)0x00,(byte)0x00};
//    System.out.println(a.intValue());


//    int a=145;
//    System.out.println(decToHex(183));
//
//    int var1 = 1;
//    int var2 = 183 >> 8;
//    int var3 = 183 & 255;
//    String var4 = Integer.toHexString(var2);
//    String var5 = Integer.toHexString(var3);
//    if(var4.length() > 2) {
//      do {
//        if(var1 > 1) {
//          var2 >>= 8;
//        }
//        var4 = Integer.toHexString(var2 >> 8);
//        var5 = var5 + Integer.toHexString(var2 & 255);
//        ++var1;
//      } while(var4.length() > 2);
//    }
//    if(var4.length() < 2) {
//      var4 = "0" + var4;
//    }
//    if(var5.length() < 2) {
//      var5 = "0" + var5;
//    }
//    System.out.println(var5 + var4);


//    int a=10;
//    System.out.println(decToHex(a));
  }
}
